set doublewide on set tv ntsc ;' ** Monster Maze - BydoEmpire @Atari Age ** const SCREEN_WIDTH=160 const SCREEN_HEIGHT=192 const SCREEN_COLUMNS=20 const SCREEN_ROWS=12 const SCREEN_EDGE_TOP=8 const SCREEN_EDGE_BOTTOM=176 const SCREEN_EDGE_LEFT=4 const SCREEN_EDGE_RIGHT=152 const DEBUG_SKIPMAINMENU=1 ; 'skip main menu for ease const DEBUG_SHOWERRORCODE=0 ; 'show error code const DEBUG_ALWAYSSHOWMAZE=0 ; 'always show the maze, not via torch const DEBUG_DISABLEMUSIC=1 ; 'turn off background music const DEBUG_PLACEGEMS=1 ; add gems to the maze ;'const DEBUG_SHOWTIMEINROOM=0 ; ' draw time in room in upper right corner const DEBUG_CHECKHEROTILE=0 ; '1=right, 2=left, 3=down, 4=up ;'const DEBUG_ENEMYDESTINATION=0 ;' draw a little sprite at the enemy destination const DEBUG_FORCEENEMYTYPE=0 ; ' testing mummy AI, spawn only 1 of enemytype value-1 (i.e. spider=1, mummy=2, etc) ;'const DEBUG_FORCE_ITEMS=0 ; 'force all rooms to have this item const STARTING_ITEMS=0 ; 'bits for which items you start with (map, etc) const STARTING_LEVEL=0 ; 'force starting on a given level const TORCH_TIME=20 const FLASH_TIME=100 const DIFFICULTY_EASY=0 const DIFFICULTY_NORMAL=1 const DIFFICULTY_HARD=2 ;' bit flags for extra_item_bits const ITEM_BIT_MAP = 1 const ITEM_BIT_KEY = 2 const ITEM_BIT_RING = 4 const ITEM_BIT_GARLIC = 8 const ITEM_BIT_CROSS = 16 const ITEM_BIT_TORCH = 32 const ENEMY_SPIDER=0 const ENEMY_MUMMY=1 const ENEMY_BAT=2 const ENEMY_WITCH=3 const NUM_ENEMY_TYPES=4 const ENEMY_INVALID=255 ;'if we add more than 16 enemies we need to udpate size of enemies_killed[] ;' first byte is which level (0-3) ;' next byte is which flag const TILE_FLAG_NONE=0 const TILE_CHANGE_STALAGS=1 ;' convert stalagmites to level_specific things const MAX_ENEMIES=7 ; ' we actually have 4 enemies, but this is used to loop const MAX_ENEMIES_AT_ONCE=4 ; ' cap how many enemies we can have on screen before slowdown const MAX_ENEMIES_AT_ONCE_BOSS=3 ; ' cap how many enemies we can have on screen before slowdown (boss room) const AI_DEFAULT=0 ;' default (move towards player) const AI_WANDER=1 const AI_FIXED=2 const AI_FLY=3 const AI_WARP=4 const AI_FIXED_CHASE=$12 const AI_BIT_CHASE=$10 const EN_IDX_BASEHEALTH=0 const EN_IDX_DMG=1 const EN_IDX_AI=2 const EN_IDX_XVEL=3 const EN_IDX_YVEL=4 const EN_IDX_VEL=5 const EN_IDX_CHASEVEL=6 const EN_IDX_WIDTH=7 const EN_IDX_HEIGHT=8 ;' enemy definition - 9 bytes ;' 0. base health ;' 1. damage per frame ;' 2. behavior bits ;' {0-3} basic AI bits ($00-$0f) ;' {4 | $10} will chase if player close ($10) ;' 3,4. xvel, yvel for standard movement ;' 5. velocity (frames per step) ;' 6. chase velocity (frames per step) ;' 7,8. width (8/16), height (8/16) data enemydef_spider 1, 1 ;' base health, damage/frame AI_DEFAULT ;' behavior $28,$20 ;' xvel, yvel 2 ;' vel (chance out of 16 to move) 6 ;' chase vel 8,4 ;' width, height end data enemydef_bat 1, 1 ;' base health, damage/frame AI_BIT_CHASE ;' behavior $30,$22 ;' xvel, yvel 3 ;' vel (chance out of 16 to move) 5 ;' chase vel 8,4 ;' width, height end data enemydef_witch 10, 2 ;' base health, damage/frame AI_BIT_CHASE ;' behavior $50,$40 ;' xvel, yvel 6 ;' vel (chance out of 16 to move) 8 ;' chase vel 8,16 ;' width, height end data enemydef_mummy 10, 2 ;' base health, damage/frame $11 ;' behavior $50,$40 ;' xvel, yvel 6 ;' vel (chance out of 16 to move) 8 ;' chase vel 8,16 ;' width, height end const BKGD_SFX_NONE = 0 const BKGD_SFX_ECHO1 = 1 const BKGD_SFX_TOM1 = 3 const BKGD_SFX_TOM2 = 4 const BKGD_SFX_ECHO2 = 5 const BKGD_SFX_ECHO3 = 6 const BKGD_SFX_ECHO4 = 7 const BKGD_SFX_L2_TUNE1 = 8 const BKGD_SFX_L2_TUNE2 = 9 const BKGD_SFX_L2_TUNE3 = 10 const BKGD_SFX_POUND1 = 11 const BKGD_SFX_POUND2 = 12 ; 'tsound channel, [frequency], [waveform],[volume] ; 'frames (each ~1sec), freq, waveform, vol (vol=0 means silence for this many frames) data music_level0 20, BKGD_SFX_ECHO1, 2 21, BKGD_SFX_ECHO1, 3 23, BKGD_SFX_ECHO1, 1 22, BKGD_SFX_ECHO1, 1 28, BKGD_SFX_ECHO1, 2 end data music_level1 8, BKGD_SFX_POUND1, 1 8, BKGD_SFX_POUND2, 1 8, BKGD_SFX_POUND1, 1 8, BKGD_SFX_POUND2, 1 4, BKGD_SFX_POUND1, 1 4, BKGD_SFX_POUND1, 1 16, BKGD_SFX_POUND2, 1 8, BKGD_SFX_POUND2, 1 8, BKGD_SFX_POUND1, 1 8, BKGD_SFX_POUND2, 1 8, BKGD_SFX_POUND1, 1 4, BKGD_SFX_POUND2, 1 4, BKGD_SFX_POUND2, 1 24, BKGD_SFX_POUND1, 1 end data music_level2 22, BKGD_SFX_L2_TUNE1, 1 24, BKGD_SFX_L2_TUNE3, 1 22, BKGD_SFX_L2_TUNE1, 1 28, BKGD_SFX_L2_TUNE2, 1 24, BKGD_SFX_L2_TUNE1, 1 26, BKGD_SFX_L2_TUNE3, 2 24, BKGD_SFX_L2_TUNE1, 2 32, BKGD_SFX_L2_TUNE2, 2 end data music_level3 28, BKGD_SFX_ECHO3, 2 26, BKGD_SFX_ECHO4, 2 22, BKGD_SFX_ECHO3, 1 28, BKGD_SFX_ECHO2, 1 24, BKGD_SFX_ECHO3, 1 32, BKGD_SFX_ECHO2, 1 end data music_level_boss 2, BKGD_SFX_TOM2, 0 2, BKGD_SFX_TOM1, 1 2, BKGD_SFX_TOM2, 0 2, BKGD_SFX_TOM1, 1 1, BKGD_SFX_TOM2, 0 1, BKGD_SFX_TOM2, 0 4, BKGD_SFX_TOM1, 1 end const PAUSE_DEBOUNCE = 16 alphadata text_title alphabet_wd 'monster maze' end alphadata text_pressbutton alphabet_wd 'press button' end /* alphadata text_tostart alphabet_wd 'to start' end */ alphadata text_easy alphabet_wd 'easy' end alphadata text_normal alphabet_wd 'normal' end alphadata text_hard alphabet_wd 'hard' end alphadata text_newgame alphabet_wd 'new game' end alphadata text_continue alphabet_wd 'continue' end ;' enemy data definitions const enemydef_bat_lo=#enemydef_bat const enemydef_bat_len=enemydef_bat_length const enemydef_spider_lo=#enemydef_spider const enemydef_spider_len=enemydef_spider_length const enemydef_mummy_lo=#enemydef_mummy const enemydef_mummy_len=enemydef_mummy_length const enemydef_witch_lo=#enemydef_witch const enemydef_witch_len=enemydef_witch_length const music_level0_lo=#music_level0 const music_level0_len=music_level0_length const music_level1_lo=#music_level1 const music_level1_len=music_level1_length const music_level2_lo=#music_level2 const music_level2_len=music_level2_length const music_level3_lo=#music_level3 const music_level3_len=music_level3_length const music_level_boss_lo=#music_level_boss const music_level_boss_len=music_level_boss_length /*******************************************************/ const HERO_XVEL=$80 ; '$70 const HERO_YVEL=$70 ; '$60 const HERO_XVEL_FAST=$90 const HERO_YVEL_FAST=$80 const HERODIR_UP=0 const HERODIR_LEFT=1 const HERODIR_DOWN=2 const HERODIR_RIGHT=3 const MOVING_BIT_UP=1 const MOVING_BIT_LEFT=2 const MOVING_BIT_DOWN=4 const MOVING_BIT_RIGHT=8 ;' room/map constants const UNINITIALIZED_ROOM = 15 const BIT_RIGHT=1 const BIT_LEFT=2 const BIT_DOWN=4 const BIT_UP=8 const SHAKE_TIME_HIT=5 const SHAKE_TIME_DYING=100 dim weaponptr_lo=a dim weaponptr_hi=b dim weaponptr_len=c dim weapon_dmg=d dim weapon_time=e dim weapon_debounce=f dim weapon_pal=g dim health_bcd=h; 'also uses i,j ;' var k-m free dim rawbuffer_rowptr_lo=k ; '2 byte pointer to current rawbuffer row dim rawbuffer_rowptr_hi=l dim rawbuffer_rowptr_len=m dim backbuffer_rowptr_lo=n ; '2 byte pointer to current backbuffer row dim backbuffer_rowptr_hi=o dim backbuffer_rowptr_len=p dim cur_enemyptr_lo=q; ; 'used in enemy loop to point to enemy data structure dim cur_enemyptr_hi=r; dim cur_enemyptr_len=s; dim music_ptr_lo=t ; 'saving this for later in case we need one more pointer dim music_ptr_hi=u dim music_ptr_len=v ;' reserving x, y and z for local functions ;' some handy temp variables... dim tempx=var0 dim tempy=var1 dim temploop=var2 ;' joystick fire debounce... dim button0_debounce=var3 ;' button0 is select dim button1_debounce=var4 ;' button1 is fire dim pause_debounce=var5 ; ' debounce flag for pause button dim tx1=var6 dim tx2=var7 dim tx3=var8 dim ty1=var9 dim ty2=var10 dim ty3=var11 dim torch_timer=var12 dim force_refresh=var13 dim showmaze_timer=var14 dim spawned_boss=var15 dim shake_timer=var43 ; 'frames to shake screen dim enemy_frame=var44 ; 'global for all enemies dim current_room_walls=var45 ; 'which screen type is the current room? dim game_stage=var46 ; 'see consts above (menu, gameplay, ghost, tc) dim dungeon_level=var47 ; '0-based level of the dungeon (controls difficulty, enemies, tileset, etc) dim rooms_visited=var48 ; 'how many rooms has the player visited? dim cur_music_frame=var50 dim cur_music_note=var51 dim t1=var52 ; 'temp variable dim t2=var53 ; 'temp variable dim t3=var54 ; 'temp variable dim extra_item_bits=var55 ; 'bits for extra items (map, etc) dim room_interior=var56; ; 'used for DEBUG_CYCLEINTERIORS dim difficulty=var60 dim total_rooms_visited=var62 dim wongame_page=var63 dim continuegame=var66 ;' start new or restore a game? const STAGE_MENU=0 const STAGE_GAMEPLAY=1 const STAGE_MAP=2 const STAGE_LOSTLIFE=3 const STAGE_GAMEOVER=7 const TICKS_TO_REMOVE_GATES = 10 ; 'each tick is approximately 1 sec. const TICKS_TO_REMOVE_GATES_FAST = 5 ; 'each tick is approximately 1 sec. ;' background/maze tile blocks const TILE_BLOCK_L=2 const TILE_BLOCK_R=4 const TILE_COLUMN=6 const TILE_GATE=8 const TILE_TOPBLOCK_L=10 const TILE_TOPBLOCK_R=12 const TILE_ITEM=14 ;'replace with item' const TILE_GRAVE_1=18 const TILE_GRAVE_2=20 const TILE_GRAVE_3=22 const TILE_GRAVE_4=24 ;' item tile IDs - each one is 2 bytes (gravestone = 60 = #30x2) const TILE_FIRST_ITEM=50 const TILE_GRAVESTONE=50 const TILE_STAIRS_UP=52 const TILE_STAIRS=54 const TILE_MAP=56 const TILE_POTION=60 const TILE_SWORD=62 const TILE_BOW=64 const TILE_SCROLL=66 const TILE_FIRST_TREASURE=68 const TILE_COINS=68 const TILE_GOLD=70 const TILE_NECKLACE=78 const TILE_CHALICE=80 const TILE_CROWN=82 const TILE_LAST_TREASURE=82 ; ' can't have more than 32 treasure slots const TILE_LAST_ITEM=98 ;' monster maze items const TILE_KEY=58 const TILE_CHEST_CLOSED=60 const TILE_CHEST_OPEN=62 const TILE_GEM=72 const TILE_STAKE=88 const TILE_TORCH=90 const TILE_CROSS=92 const TILE_GARLIC_1=94 const TILE_GARLIC_2=96 const TILE_RING=98 const WONGAME_ENEMIES=15 ;' NUM_ENEMY_TYPES const WONGAME_TREASURES=24 ;' NUM_ENEMY_TYPES + (TILE_LAST_TREASURE-TILE_FIRST_TREASURE) const WONGAME_ROOMS=27 ;' NUM_ENEMY_TYPES + (TILE_LAST_TREASURE-TILE_FIRST_TREASURE)+3 const HEALTH_STARTING=50 const HEALTH_RESURRECTED=25 const GHOST_TIMER=30 rem $2200-$27FF Variable Chunk ;' memset $2200 0 $5ff ;'************************ ;' Reserve 280 bytes for mapdata! Enough to hold tiles for a full screen at 160x224 (20x14 map, even though I use 20x12) dim currentmapdata = $2200 ; 'copy of current screen tiles - 280 bytes ;'dim generated_level = $2318 ; 'generated 8x8 map data - 64 bytes ;'dim wip_level_stack = $2358 ; 'wip level stack - 64 bytes, but that's probably overkill dim dots_left = $2398 ;'dim bullet_frame = $2399 ;'dim bullet_palette = $239A dim enemies_spawned_in_room = $239b ; 'don't keep spawning enemies forever in one room dim time_in_room = $239c ; 'how many 'ticks' spent in the current room. Scale TBD... dim num_lives=$239d ; ' from which side did hero enter? dim debugroomcode=$239e; ; ' need 3 bytes for bcd value dim debugroomcode2=$239f; ; dim debugroomcode3=$23a0; ; dim reached_stairs=$23a1; ; 'hero reached the stairs at the end of the level - go to the next level dim current_room_number=$23a2 ; '0-63 dim curen=$23a3 ; 'just a loop counter used where temploop is taken dim room_status_bits=$23a4 ; ' flag that tracks properties of the current room, like gate status dim initial_room_number=$23a5 ; ' which room did player start in? dim next_enemy_spawn_tick=$23a6 ; ' tick at which we next check to spawn an enemy dim player_move_delay_frames=$23a7 ; 'frames to delay player movement, used for keys,e tc. dim errorcode = $23A8 ; '3 byte bcd value dim errorcode2 = $23A9 ; '3 byte bcd value dim errorcode3 = $23Aa ; '3 byte bcd value ;'dim item_tile_x = $23AB ; 'if there's an item here, which tile is it on? ;'dim item_tile_y = $23AC ; 'if there's an item here, which tile is it on? ;'dim exp_bonus=$23AD ; 'exploration bonus - points for how many rooms you explored dim cur_enemy_dir=$23AE ; 'temp variable used to determine direction of enemy's next move dim cur_enemy_height=$23AF ; 'temp variable used for height of the enemy being processed ;' note enemy1_x is used in save_enemy_state, and if we change order we need to update that dim enemy1_x=$23B0 ; '8 bytes, 1 for each enemy dim enemy2_x=$23B1 dim enemy3_x=$23B2 dim enemy4_x=$23B3 dim enemy5_x=$23B4 dim enemy6_x=$23B5 dim enemy7_x=$23B6 dim enemy8_x=$23B7 dim enemy1_y=$23B8 ; '8 bytes, 1 for each enemy dim enemy2_y=$23B9 dim enemy3_y=$23BA dim enemy4_y=$23BB dim enemy5_y=$23BC dim enemy6_y=$23BD dim enemy7_y=$23BE dim enemy8_y=$23BF ;' current health (0 means not active) dim enemy1_health=$23C0 dim enemy2_health=$23C1 dim enemy3_health=$23C2 dim enemy4_health=$23C3 dim enemy5_health=$23C4 dim enemy6_health=$23C5 dim enemy7_health=$23C6 dim enemy8_health=$23C7 ;' destination position they're moving towards dim enemy1_desttilex=$23C8 dim enemy2_destxtile=$23C8 dim enemy3_destxtile=$23CA dim enemy4_destxtile=$23CB dim enemy5_destxtile=$23CC dim enemy6_destxtile=$23CD dim enemy7_destxtile=$23CE dim enemy8_destxtile=$23CF dim enemy1_desttiley=$23D0 dim enemy2_destytile=$23D1 dim enemy3_destytile=$23D2 dim enemy4_destytile=$23D3 dim enemy5_destytile=$23D4 dim enemy6_destytile=$23D5 dim enemy7_destytile=$23D6 dim enemy8_destytile=$23D7 ;' delay before picking new destination dim enemy1_curtilex=$23D8 dim enemy2_curxtile=$23D9 dim enemy3_curxtile=$23DA dim enemy4_curxtile=$23DB dim enemy5_curxtile=$23DC dim enemy6_curxtile=$23DD dim enemy7_curxtile=$23DE dim enemy8_curxtile=$23DF dim enemy1_curtiley=$23E0 dim enemy2_curytile=$23E1 dim enemy3_curytile=$23E2 dim enemy4_curytile=$23E3 dim enemy5_curytile=$23E4 dim enemy6_curytile=$23E5 dim enemy7_curytile=$23E6 dim enemy8_curytile=$23E7 ;' enemy type dim enemy1_type=$23E8 dim enemy2_type=$23E9 dim enemy3_type=$23EA dim enemy4_type=$23EB dim enemy5_type=$23EC dim enemy6_type=$23ED dim enemy7_type=$23EE dim enemy8_type=$23EF ; ' what direction are they moving? dim enemy1_dir=$23F0 dim enemy2_dir=$23F1 dim enemy3_dir=$23F2 dim enemy4_dir=$23F3 dim enemy5_dir=$23F4 dim enemy6_dir=$23F5 dim enemy7_dir=$23F6 dim enemy8_dir=$23F7 dim enemy1_vel=$23F8 dim enemy2_vel=$23F9 dim enemy3_vel=$23FA dim enemy4_vel=$23FB dim enemy5_vel=$23FC dim enemy6_vel=$23FD dim enemy7_vel=$23FE dim enemy8_vel=$23FF ; $23f8 free ;dim room_item_list = $23F8 ; 'list of items in each room 64 bytes (one for each room, contains 255 or item #) ; distribution of enemies per dungeon level dim enemy_chance_type=$2438 ; up to 8 enemies per level, 8 bytes dim enemy_chance_weight=$2440 ; up to 8 enemies per level, 8 bytes dim hero_xvel_add=$2448 dim hero_yvel_add=$2449 dim hero_xpos=$244a dim hero_ypos=$244b dim frame=$244c dim herodir=$244d ; 'up=0 left=1 down=2 right=3 dim moving=$244e dim heroframe=$244f dim selected_weapon=$2450 dim fire_angle=$2451 ; 'up=0 right=4 down=8 left=12 dim hero_xvel=$2452 dim hero_yvel=$2453 dim hero_tile=$2454 dim hero_level_x=$2455 ; 'which x/y room location within the level dim hero_level_y=$2456 ; 'which x/y room location within the level dim weapon0_level=$2457 dim weapon1_level=$2458 dim weapon2_level=$2459 dim weapon3_level=$245a dim bullet1_dmg=$245b dim bullet2_dmg=$245c dim bullet3_dmg=$245d dim current_spawn_chance=$245e dim initial_spawn_chance=$245f dim initial_spawn_count=$2460 dim current_enemy_buffer=$2461 dim prev_game_stage=$2462 dim bullet1_pal=$2463 dim bullet2_pal=$2464 dim bullet3_pal=$2465 dim hero_curtilex=$2467 dim hero_curtiley=$2468 dim hero_prevtilex=$2469 dim hero_prevtiley=$246a dim dest_tilex=$246b dim dest_tiley=$246c dim moving_dir=$246d ;' $2200-$27FF Variable Chunk ;' 280 (x118) bytes - enough to hold tiles for a full screen at 160x224 (20x14 map, even though I use 20x12) ;backbuffer_rowptr_lo = $3c ;backbuffer_rowptr_hi = $26 dim mapdata_backbuffer=$2500 ; 'to copy into curmapdata for display const mapdata_backbuffer_row00_hi=$25 const mapdata_backbuffer_row00=$00 const mapdata_backbuffer_row01=$14 const mapdata_backbuffer_row02=$28 const mapdata_backbuffer_row03=$3c const mapdata_backbuffer_row04=$50 const mapdata_backbuffer_row05=$64 const mapdata_backbuffer_row06=$78 const mapdata_backbuffer_row07=$8c const mapdata_backbuffer_row08=$a0 const mapdata_backbuffer_row09=$b4 const mapdata_backbuffer_row10=$c8 const mapdata_backbuffer_row11=$dc ;const mapdata_backbuffer_row12=$25f0 ;const mapdata_backbuffer_row13=$2604 ;backbuffer_rowptr_lo = $18 ;backbuffer_rowptr_hi = $27 dim mapdata_rawmap=$2618 ; 'starting map info, including gems, etc const mapdata_rawbuffer_row00_hi=$26 const mapdata_rawbuffer_row00=$18 const mapdata_rawbuffer_row01=$2c const mapdata_rawbuffer_row02=$40 const mapdata_rawbuffer_row03=$54 const mapdata_rawbuffer_row04=$68 const mapdata_rawbuffer_row05=$7c const mapdata_rawbuffer_row06=$90 const mapdata_rawbuffer_row07=$a4 const mapdata_rawbuffer_row08=$b8 const mapdata_rawbuffer_row09=$cc const mapdata_rawbuffer_row10=$e0 const mapdata_rawbuffer_row11=$f4 ;const mapdata_rawbuffer_row12=$2708 ;const mapdata_rawbuffer_row13=$271c ;'next free at $2730 ;' -Set ROM size- ;' Ths sets the ROM size and format of your game. The default is 32k, and valid values for ;' the romsize are 32k, 48k, 128k, 128kRAM, 128kBANKRAM, 256k, 256kRAM, 256kBANKRAM, 512k, ;' 512kRAM, 512BANKRAM. Formats larger than 48k are bankswitching formats, with many 16k banks. ;' While you need to bankswitch to access all banks except the last, which is always present. ;' If you use bankswitching format, you'll need to use the bankswitching goto/gosub commands ;' to move between different banks. The formats with RAM on the end of the name provide an ;' extra 16k of RAM from $4000-$7fff. You can access this extra RAM by naming it with dim, ;' and using the memory through regular variable access. set romsize 48k /*******************************************************/ ;' Set up graphics ** /*******************************************************/ ;' -Set Display Mode- ;' This command sets the current graphics display mode. You may choose between 160A, 320A, 320B. ;' It should be noted that these modes are also capable of displaying 160B, 320C, and 320D ;' formatted graphics, respectively. displaymode 160A set screenheight 192 ;'set pauseroutine off ;' set up high score cart support set hssupport $5744 set hsseconds 4 set hsscoresize 6 set hscolorbase $FE set hsgameranks 100000 'wizard' 075000 'sorcerer' 050000 'acolyte' 025000 'apprentice' 000005 'fodder' /*******************************************************/ ;' include art assets /*******************************************************/ incgraphic gfx/tileset_test.png 160a 0 1 2 3 incgraphic gfx/scoredigits_8_wide_centered.png incgraphic gfx/alphabet_wd.png 160a 0 2 1 3 ;' up left down right incgraphic gfx/hero_l1.png incgraphic gfx/hero_l2.png incgraphic gfx/hero_l3.png incgraphic gfx/hero_l4.png ;incgraphic gfx/hero_l5.png incgraphic gfx/hero_r1.png incgraphic gfx/hero_r2.png incgraphic gfx/hero_r3.png incgraphic gfx/hero_r4.png ;incgraphic gfx/hero_r5.png ;' end current graphics block and start a new one here newblock incgraphic gfx/hiscorefont.png 320A incgraphic gfx/shadow_ul.png incgraphic gfx/shadow_ur.png incgraphic gfx/shadow_lr.png incgraphic gfx/shadow_ll.png ;' include enemy sprites incgraphic gfx/spider_l1.png incgraphic gfx/spider_l2.png incgraphic gfx/spider_r1.png incgraphic gfx/spider_r2.png incgraphic gfx/bat1.png incgraphic gfx/bat2.png incgraphic gfx/bat3.png incgraphic gfx/bat4.png incgraphic gfx/mummy_l_1c.png incgraphic gfx/mummy_l_2c.png incgraphic gfx/mummy_r_1c.png incgraphic gfx/mummy_r_2c.png incgraphic gfx/witch_l1.png incgraphic gfx/witch_l2.png incgraphic gfx/witch_l3.png incgraphic gfx/witch_l4.png incgraphic gfx/witch_r1.png incgraphic gfx/witch_r2.png incgraphic gfx/witch_r3.png incgraphic gfx/witch_r4.png incgraphic gfx/drac_r1.png 160b const PAL_HERO=0 const PAL_BKGD=1 const PAL_BAT=2 const PAL_GRUNT=2 const PAL_SPIDER=2 const PAL_ARROW=2 const PAL_BOSS=3 const PAL_MUMMIES=3 const PAL_WITCH=3 const PAL_GREYBAT=3 const PAL_SHADOW=4 const PAL_SNAKE=4 const PAL_TENTACLE=5 const PAL_GOBLINS=6 const PAL_MAP=7 const PAL_GOLEM=7 const PAL_PHASESPIDER=7 ;' load current high scores on boot hiscoreload ;' not restoring a game at first boot continuegame=0 ;' initialize game variables regardless of mode (i.e. what's needed to do menu) GameStage_MainMenu_Reset BACKGRND=$00 ; for now, force background to black on every level ;' setup Palette 0 (hero) ;PAL_HERO P0C1=$f4 ; jacket/hat P0C2=$f6 ; arm P0C3=$18 ; face ;' setup Palette 1 (background tiles?) ; PAL_BKGD P1C1=$12 ;'gold P1C2=$F6 ;'tan P1C3=$Fc ;'brown ;' setup Palette 2 (Minions) ; PAL_GRUNT, PAL_BAT, PAL_SPIDER P2C1=$c1 ; dark green (legs) P2C2=$42 ; red (eyes) P2C3=$c3 ; med green (body) ;' setup Palette 3 (Boss) ;' PAL_MUMMY, PAL_WITCH P3C1=$04 ;'dark grey? P3C2=$08 ;'med grey P3C3=$0c ;'light grey ;' setup Palette 4 (Shadows) ; PAL_SHADOW P4C1=$00 ; black P4C2=$01 ; dark grey P4C3=$02 ; light grey ;' setup Palette 5 (Tentacle) P5C1=$40 ;'red P5C2=$46 ;'med red P5C3=$48 ;'light red ;' setup Palette 6 (spiders) P6C1=$f2 ;'dark grey? P6C2=$c1 ;'med grey P6C3=$0c ;'light grey ;' setup Palette 7 (map) P7C1=$12 ;'gold P7C2=$F6 ;'tan P7C3=$Fc ;'brown game_stage=STAGE_MENU clearscreen debugroomcode=0 ; 'debug bits for which hex value we're looking at for each room (walls, interior, etc) t=0:u=0 ; 'clearing out for bcd debugroomcode value current_room_walls=0 room_status_bits=0 errorcode = $0 backbuffer_rowptr_lo = $0 backbuffer_rowptr_len = 0 rawbuffer_rowptr_lo = $0 rawbuffer_rowptr_len = 0 button0_debounce=255 ;' force an initial delay in case we're coming back from HSC or holding button at boot button1_debounce=255 ;' force an initial delay in case we're coming back from HSC or holding button at boot pause_debounce=0 extra_item_bits=STARTING_ITEMS player_move_delay_frames=0 frame=0 t1=0 ; 'joystick debounce in menu difficulty=DIFFICULTY_NORMAL weaponptr_lo=$0 weaponptr_hi=0 weaponptr_len=0 weapon_dmg=0 weapon_time=0 weapon_debounce=0 weapon_pal=0 ;' activate the graphics area with our tiles... characterset tileset_test if DEBUG_SKIPMAINMENU<>0 then goto GameStage_StartNewGame /*****************/ GameStage_MainMenu ;'plotchars text_begin 2 48 6 8 plotvalue scoredigits_8_wide_centered 2 health_bcd 2 2 0 plotvalue scoredigits_8_wide_centered 2 score0 6 1 11 ;' draw some cool stuff, but TODO: explain it z=0 ; 'used for menu page t1=1; 'global debounce t2=continuegame; 'difficulty or new game/continue - which menu option? t3=continuegame ;' was continuegame an option going in? clearscreen gosub mainmenu_page0 savescreen ;' check both buttons to start the game mainmenu_check_button1 frame=frame+1 if frame<8 then goto mainmenu_check_difficulty ;' no button pressed then clear debounce and return if button0_debounce>0 && joy0fire0 then goto mainmenu_check_button2 if !joy0fire0 then button0_debounce=0: goto mainmenu_check_button2 goto mainmenu_startgame mainmenu_check_button2 if button1_debounce>0 && joy0fire1 then goto mainmenu_check_difficulty if !joy0fire1 then button1_debounce=0: goto mainmenu_check_difficulty goto mainmenu_startgame mainmenu_check_difficulty ;' t1 is global debounce if t1<>0 then goto mainmenu_process if joy0down || joy0up then t1=1 : t2 = 1-t2 if t2=1 then goto mainmenu_check_continue if joy0left then t1=1:difficulty=difficulty-1 : playsfx sfx_gotomap if difficulty>DIFFICULTY_HARD then difficulty=DIFFICULTY_HARD if joy0right then t1=1:difficulty=difficulty+1 : playsfx sfx_gotomap if difficulty>DIFFICULTY_HARD then difficulty=DIFFICULTY_EASY goto mainmenu_process mainmenu_check_continue ;' if we didn't enter the menu with the possibility of continuing, just skip it if t3=0 then goto mainmenu_process if joy0left || joy0right then t1=1 : continuegame=1-continuegame : playsfx sfx_gotomap mainmenu_process if !joy0down && !joy0up && !joy0left && !joy0right then t1=0 ;' check if we should fip to new page, every X frames if (frame & $ff)<>0 then goto mainmenu_drawscreen ;' new page z=z+1 ;'if z>2 then z=0 clearscreen gosub mainmenu_page0 ;'if z=2 then gosub mainmenu_page2 savescreen drawscreen mainmenu_drawscreen restorescreen x = (frame/8)&3 plotchars text_title PAL_BKGD 32 3 12 if t2=0 && x=0 then goto mainmenu_draw_continue if difficulty=DIFFICULTY_EASY then plotchars text_easy 2 64 5 4 if difficulty=DIFFICULTY_NORMAL then plotchars text_normal 2 56 5 6 if difficulty=DIFFICULTY_HARD then plotchars text_hard 2 64 5 4 mainmenu_draw_continue if t2<>0 && x=0 then goto mainmenu_draw_do_draw if continuegame=0 then plotchars text_newgame 2 48 6 8 if continuegame<>0 then plotchars text_continue 2 48 6 8 mainmenu_draw_do_draw drawscreen goto mainmenu_check_button1 mainmenu_startgame ;' remember we're holding button 0 button0_debounce = 255 button1_debounce = 255 temp1 = frame&$ff if temp1=0 then temp1=1 ; can't allow rand to be zero or it'll get stuck there rand=temp1 playsfx sfx_foundgrave goto GameStage_StartNewGame mainmenu_page0 ;' copy screen to map location memcpy currentmapdata screenmap_level1 280 plotmap currentmapdata 1 0 0 20 12 pokechar currentmapdata 6 9 20 12 TILE_COINS pokechar currentmapdata 8 9 20 12 TILE_GOLD pokechar currentmapdata 10 9 20 12 TILE_GEM pokechar currentmapdata 12 9 20 12 TILE_NECKLACE pokechar currentmapdata 14 9 20 12 TILE_CHEST_CLOSED return /*****************/ GameStage_GameOver playsfx sfx_gotomap clearscreen drawscreen gameover_drawattract ;' allow player to enter their initials gamedifficulty=difficulty drawhiscores single drawhiscores attract goto GameStage_MainMenu_Reset /*****************/ GameStage_StartNewGame ;' Initialize Gameplay Variables at start of a new GAME debugroomcode=0 ; 'debug bits for which hex value we're looking at for each room (walls, interior, etc) t=0:u=0 ; 'clearing out for bcd debugroomcode value score0=0 score1=0 num_lives=3 reached_stairs=0 dungeon_level=STARTING_LEVEL game_stage = STAGE_GAMEPLAY prev_game_stage = STAGE_GAMEPLAY total_rooms_visited=0 GameStage_StartNewLevel BACKGRND=$00 ; for now, force background to black on every level ;' Initialize Gameplay Variables at start of each LEVEL of the dungeon current_room_number=0; ; 'which room player is currently in initial_room_number=0 current_room_walls=0 errorcode = $0 backbuffer_rowptr_lo = $0 backbuffer_rowptr_len = 0 rawbuffer_rowptr_lo = $0 rawbuffer_rowptr_len = 0 room_status_bits=0 extra_item_bits=extra_item_bits&$fc ; 'strip off map & key, as they're level-specific.. keep magic items extra_item_bits=extra_item_bits|STARTING_ITEMS torch_timer=TORCH_TIME showmaze_timer=0 GameStage_LostLife spawned_boss=0 button0_debounce=0 button1_debounce=0 shake_timer=0 force_refresh=1 moving_dir=0 hero_curtilex = 10 hero_curtiley = 5 hero_xpos=hero_curtilex*8 hero_ypos=hero_curtiley*16 gosub set_hero_curtile dest_tilex = hero_curtilex dest_tiley = hero_curtiley hero_prevtilex=255; hero_prevtiley=255; time_in_room=0 hero_level_x = rand&7 ; '0 hero_level_y = rand&7 ; '0 hero_xvel=0 : hero_xvel_add=HERO_XVEL hero_yvel=0 : hero_yvel_add=HERO_YVEL hero_tile=0 heroframe=0 herodir=HERODIR_RIGHT fire_angle=4 player_move_delay_frames=0 if (extra_item_bits&ITEM_BIT_RING)<>0 then hero_xvel_add=HERO_XVEL_FAST if (extra_item_bits&ITEM_BIT_RING)<>0 then hero_yvel_add=HERO_YVEL_FAST ;' only restore 10 health, not all the way if difficulty=DIFFICULTY_EASY then goto GameStart_Easy if difficulty=DIFFICULTY_NORMAL then goto GameStart_Normal if difficulty=DIFFICULTY_HARD then goto GameStart_Difficulty_Done GameStart_Easy goto GameStart_Difficulty_Done GameStart_Normal ;'goto GameStart_Difficulty_Done ;'drop through... GameStart_Difficulty_Done rooms_visited=0 cur_music_frame=0 cur_music_note=0 room_interior=0 current_spawn_chance=0 initial_spawn_chance=0 initial_spawn_count=0 ;' initialize enemy spawn chances memset enemy_chance_type ENEMY_INVALID 8 memset enemy_chance_weight 0 8 reached_stairs=reached_stairs&$e; ; 'bit 0=reached stairs, reset. bit1=flag to reposition hero if (dungeon_level&3)=1 then goto GameStart_setpalette_level1 if (dungeon_level&3)=2 then goto GameStart_setpalette_level2 if (dungeon_level&3)=3 then goto GameStart_setpalette_level3 GameStart_setpalette_level0 P1C1=$c0 : P1C2=$c6 ; PAL_BKGD green ; PAL_GRUNT (spiders) P2C1=$11 ; dark brown (body) P2C2=$14 ; gold (highlight) P2C3=$42 ; red (eyes) ; PAL_BOSS (witch) P3C1=$f2 ; (robe) P3C2=$e5 ; (arms) P3C3=$c3 ; med green (face) goto GameStart_clearenemies GameStart_setpalette_level1 P1C1=$03 : P1C2=$06 ; PAL_BKGD grey ; PAL_GRUNT (bats) P2C1=$c1 ; dark green (legs) P2C2=$42 ; red (eyes) P2C3=$c3 ; med green (body) ; PAL_BOSS (mummy or ghost?) P3C1=$04 ;'dark grey? P3C2=$08 ;'med grey P3C3=$0c ;'light grey goto GameStart_clearenemies GameStart_setpalette_level2 P1C1=$80 : P1C2=$86 ; PAL_BKGD blue P2C1=$11 ; dark brown (body) P2C2=$14 ; gold (highlight) P2C3=$42 ; red (eyes) ; PAL_BOSS (???) P3C1=$c1 ;'dark grey? P3C2=$42 ;'med grey P3C3=$c3 ;'light grey goto GameStart_clearenemies GameStart_setpalette_level3 P1C1=$12 : P1C2=$F6 ; PAL_BKGD tan ; PAL_GRUNT (bats) P2C1=$c1 ; dark green (legs) P2C2=$42 ; red (eyes) P2C3=$c3 ; med green (body) ; PAL_BOSS (???) P3C1=$04 ;'dark grey? P3C2=$08 ;'med grey P3C3=$0c ;'light grey goto GameStart_clearenemies GameStart_clearenemies characterset tileset_test ; weights are out of 64 enemy_chance_type[0] = ENEMY_SPIDER : enemy_chance_weight[0] = 24 enemy_chance_type[1] = ENEMY_BAT : enemy_chance_weight[1] = 24 enemy_chance_type[2] = ENEMY_MUMMY : enemy_chance_weight[2] = 16 enemy_chance_type[3] = ENEMY_INVALID : enemy_chance_weight[3] = 0 enemy_chance_type[4] = ENEMY_INVALID : enemy_chance_weight[4] = 0 enemy_chance_type[5] = ENEMY_INVALID : enemy_chance_weight[5] = 0 enemy_chance_type[6] = ENEMY_INVALID : enemy_chance_weight[6] = 0 enemy_chance_type[7] = ENEMY_INVALID : enemy_chance_weight[7] = 0 music_ptr_lo=music_level0_lo music_ptr_hi=music_level0_hi music_ptr_len=music_level0_length newlevel_init_enemies ;' Initialize Enemies memset enemy1_x 0 80 ;' just default these, they should get overwritten as-needed cur_enemyptr_lo=enemydef_spider_lo cur_enemyptr_hi=enemydef_spider_hi cur_enemyptr_len=enemydef_spider_len enemy_frame=0 cur_enemy_dir=BIT_UP ;' just a default, it will be set every loop cur_enemy_height=8 ;' just a default, it will be set every loop next_enemy_spawn_tick=0 curen=0; clearscreen ;' set up the initial maze for this level if game_stage<>STAGE_LOSTLIFE then gosub init_maze game_stage = STAGE_GAMEPLAY drawscreen /*****************/ MainLoop ;'main game loop for gameplay frame=frame+1 mainloop_returnfrompause if pause_debounce>0 then pause_debounce=pause_debounce-1 if (frame&$3f)<>0 then goto mainloop_process_movement ;' every X frames (~1 sec), udpate timers gosub check_enemy_spawn ; only check once a second... time_in_room = time_in_room+1 if torch_timer=0 then goto mainloop_process_movement torch_timer = torch_timer-1 if torch_timer=0 then extra_item_bits=extra_item_bits&$df : force_refresh=1 mainloop_process_movement ;' process movements if player_move_delay_frames=0 then gosub move_player2 if player_move_delay_frames>0 then player_move_delay_frames = player_move_delay_frames-1 gosub check_firebutton gosub update_enemies if DEBUG_DISABLEMUSIC <> 1 then gosub play_bkgd_music MainLoop_Draw ;' restore background first ;'restorescreen ;' check if we should shake the screen gosub update_screen_shake ;' what parts of the maze gets draw depends on what's lit gosub update_maze ;' then draw all the sprites gosub draw_hero gosub draw_enemies gosub draw_status ;' now actually display the screen drawscreen ;' special logic if we've reached the stairs if reached_stairs<>3 then goto MainLoop_CheckGameStage dungeon_level=dungeon_level+1 game_stage = STAGE_GAMEPLAY playsfx sfx_stairs reached_stairs=reached_stairs&0xe goto GameStage_StartNewLevel MainLoop_CheckGameStage if game_stage=STAGE_GAMEOVER then goto GameStage_GameOver if game_stage=STAGE_MENU then goto GameStage_MainMenu_Reset if game_stage=STAGE_LOSTLIFE then goto GameStage_LostLife goto MainLoop /****************************************************/ draw_map_background ;' copy empty tile here clearscreen memset currentmapdata 0 280 plotmap currentmapdata 1 0 0 20 1 /* if (extra_item_bits&ITEM_BIT_MAP)<>0 then pokechar currentmapdata 8 10 20 12 TILE_MAP if (extra_item_bits&ITEM_BIT_KEY)<>0 then pokechar currentmapdata 9 10 20 12 TILE_KEY if (extra_item_bits&ITEM_BIT_RING)<>0 then pokechar currentmapdata 10 10 20 12 TILE_RING if (extra_item_bits&ITEM_BIT_GARLIC)<>0 then pokechar currentmapdata 11 10 20 12 TILE_HAT if (extra_item_bits&ITEM_BIT_CROSS)<>0 then pokechar currentmapdata 12 10 20 12 TILE_STAFF if (extra_item_bits&ITEM_BIT_TORCH)<>0 then pokechar currentmapdata 13 10 20 12 TILE_CLOAK */ draw_map_background_plotmap plotmap $22b4 1 0 9 20 3 return /****************************************************/ GameStage_Map /****************************************************/ gosub draw_map_background map_initialdraw ;' draw dungeon level on map screen temp1=dungeon_level+1 debugroomcode=converttobcd(temp1) plotvalue scoredigits_8_wide_centered 2 debugroomcode 1 76 0 savescreen drawscreen pause_debounce=PAUSE_DEBOUNCE playsfx sfx_gotomap map_waittounpause restorescreen gosub draw_status drawscreen if pause_debounce>0 then pause_debounce=pause_debounce-1 : goto map_waittounpause if joy0fire0 && button0_debounce=0 then button0_debounce=4 : goto map_unpause if joy0fire1 && button1_debounce=0 then button1_debounce=4 : goto map_unpause if switchpause then goto map_unpause if !joy0fire0 then button0_debounce=0 if !joy0fire1 then button1_debounce=0 goto map_waittounpause map_unpause game_stage=prev_game_stage pause_debounce=PAUSE_DEBOUNCE ;'don't let player immediately jump back to map accidentally clearscreen ;' put the background down and save the screen before the main loop. ;' this way we don't setup the background over and over again. gosub init_maze playsfx sfx_gotomap goto mainloop_returnfrompause return /****************************************************/ init_maze ;' copy basic map if (dungeon_level&3)=0 then memcpy mapdata_rawmap screenmap_level1 280 if (dungeon_level&3)=1 then memcpy mapdata_rawmap screenmap_level2 280 if (dungeon_level&3)=2 then memcpy mapdata_rawmap screenmap_level1 280 if (dungeon_level&3)=3 then memcpy mapdata_rawmap screenmap_level2 280 ;' raw map - add gems dots_left=0 for y = 1 to 10 for x = 1 to 18 t1 = peekchar(mapdata_rawmap,x,y, 20, 12) if t1=TILE_ITEM then pokechar mapdata_rawmap x y 20 12 TILE_TORCH if t1=0 && DEBUG_PLACEGEMS<>0 then dots_left = dots_left+1 : pokechar mapdata_rawmap x y 20 12 TILE_GEM next ;'x next ;'y ;' copy raw, starting map into the backbuffer memcpy mapdata_backbuffer mapdata_rawmap 280 ;' now clear it all out (except for the edges) so it's dark if DEBUG_ALWAYSSHOWMAZE = 0 then gosub blackout_maze return /****************************************************/ update_maze ; ' check if we should flash if showmaze_timer=0 then goto update_maze_checktorches showmaze_timer=showmaze_timer-1 if showmaze_timer>0 then goto update_maze_showall ; timer ran out, force an update and go back to the lit view force_refresh=1 gosub blackout_maze goto update_maze_checktorches update_maze_showall ; if we got here, the screen is flashing, show the whole maze memcpy mapdata_backbuffer mapdata_rawmap 280 goto update_maze_return update_maze_checktorches ; ' only update if hero's tile has changed gosub set_hero_curtile if DEBUG_ALWAYSSHOWMAZE <> 0 then goto update_maze_return ; force a redraw when torch runs out if force_refresh then goto update_maze_clear ; first time through (no prev value) then redraw right away if hero_prevtilex = 255 || hero_prevtiley = 255 then goto update_maze_redraw ; otherwise if play hasn't changed tiles, don't do anything if hero_curtilex = hero_prevtilex && hero_curtiley = hero_prevtiley then goto update_maze_return update_maze_clear ; 'tile has changed, clear old pos, draw new pos ; 't1 = min row, t2 = max row if hero_prevtiley <= 2 then ty1 = 1 if hero_prevtiley >= 3 then ty1 = hero_prevtiley-2 if hero_prevtiley <= 8 then ty2 = hero_prevtiley+2 if hero_prevtiley >= 9 then ty2 = 10 update_maze_clear_doclear if ty1>11 then goto update_maze_return for y=ty1 to ty2 gosub set_mapbuffer_pointers_y ; could be optimized by adding $14 to lo ptr each time through... if hero_prevtilex <= 2 then tx1 = 1 if hero_prevtilex >= 3 then tx1 = hero_prevtilex-2 if hero_prevtilex <= 16 then tx2 = hero_prevtilex+2 if hero_prevtilex >= 17 then tx2 = 18 for x=tx1 to tx2 backbuffer_rowptr_lo[[x]] = 0 next next update_maze_redraw if torch_timer>0 then goto update_maze_redraw_5x5 update_maze_redraw_3x3 if hero_curtiley <= 1 then ty1 = 1 if hero_curtiley >= 2 then ty1 = hero_curtiley-1 if hero_curtiley <= 9 then ty2 = hero_curtiley+1 if hero_curtiley >= 10 then ty2 = 10 goto update_maze_redraw_doredraw update_maze_redraw_5x5 if hero_curtiley <= 2 then ty1 = 1 if hero_curtiley >= 3 then ty1 = hero_curtiley-2 if hero_curtiley <= 8 then ty2 = hero_curtiley+2 if hero_curtiley >= 9 then ty2 = 10 update_maze_redraw_doredraw if ty1>11 then goto update_maze_return for y=ty1 to ty2 gosub set_mapbuffer_pointers_y ; could be optimized by adding $14 to lo ptr each time through... if torch_timer>0 then goto update_maze_redraw_doredraw_5x5 update_maze_redraw_doredraw_3x3 if hero_curtilex <= 1 then tx1 = 1 else tx1 = hero_curtilex-1 if hero_curtilex <= 17 then tx2 = hero_curtilex+1 else tx2 = 18 goto update_maze_redraw_doredraw_draw update_maze_redraw_doredraw_5x5 if hero_curtilex <= 2 then tx1 = 1 if hero_curtilex >= 3 then tx1 = hero_curtilex-2 if hero_curtilex <= 16 then tx2 = hero_curtilex+2 if hero_curtilex >= 17 then tx2 = 18 update_maze_redraw_doredraw_draw for x=tx1 to tx2 backbuffer_rowptr_lo[[x]] = rawbuffer_rowptr_lo[[x]] next next ; 'save off hero tile position to detect when it changes so we can redraw (above) hero_prevtilex = hero_curtilex hero_prevtiley = hero_curtiley update_maze_return force_refresh=0 ; screen <- currentmapdata <- mapdata_backbuffer <- mapdata_rawbuffer clearscreen memcpy currentmapdata mapdata_backbuffer 280 ;' plotmap mapdata palette_# x y width height [map_x_off map_y_off map_width] plotmap currentmapdata 1 0 0 20 12 savescreen return /****************************************************/ set_mapbuffer_pointers_y backbuffer_rowptr_hi = mapdata_backbuffer_row00_hi rawbuffer_rowptr_hi = mapdata_rawbuffer_row00_hi if y = 0 then backbuffer_rowptr_lo = mapdata_backbuffer_row00 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row00 if y = 1 then backbuffer_rowptr_lo = mapdata_backbuffer_row01 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row01 if y = 2 then backbuffer_rowptr_lo = mapdata_backbuffer_row02 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row02 if y = 3 then backbuffer_rowptr_lo = mapdata_backbuffer_row03 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row03 if y = 4 then backbuffer_rowptr_lo = mapdata_backbuffer_row04 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row04 if y = 5 then backbuffer_rowptr_lo = mapdata_backbuffer_row05 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row05 if y = 6 then backbuffer_rowptr_lo = mapdata_backbuffer_row06 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row06 if y = 7 then backbuffer_rowptr_lo = mapdata_backbuffer_row07 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row07 if y = 8 then backbuffer_rowptr_lo = mapdata_backbuffer_row08 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row08 if y = 9 then backbuffer_rowptr_lo = mapdata_backbuffer_row09 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row09 if y = 10 then backbuffer_rowptr_lo = mapdata_backbuffer_row10 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row10 if y >= 11 then backbuffer_rowptr_lo = mapdata_backbuffer_row11 : rawbuffer_rowptr_lo = mapdata_rawbuffer_row11 ; bounds check, we should never be resetting rows 0 and 11 if y = 0 then errorcode=$e0 if y > 11 then errorcode=$e1 return /****************************************************/ blackout_maze for y = 1 to 10 for x = 1 to 18 pokechar mapdata_backbuffer x y 20 12 0 next ;'x next ;'y return /****************************************************/ place_key ; place key on opposite side of maze as hero if hero_curtilex<=9 && hero_curtiley<5 then x=18:y=9 if hero_curtilex>9 && hero_curtiley<5 then x=1:y=9 if hero_curtilex<=9 && hero_curtiley>=5 then x=18:y=0 if hero_curtilex>9 && hero_curtiley>=5 then x=1:y=0 place_key_check_y y=y+1 if y>10 then y=1 place_key_check_x t1 = peekchar(mapdata_rawmap,x,y, 20, 12) if t1=0 then goto place_key_return x=x+1 if x>18 then x=1:goto place_key_check_y goto place_key_check_x place_key_return force_refresh=1 playsfx sfx_stairs pokechar mapdata_rawmap x y 20 12 TILE_KEY ; if we're always showing the maze, we need to put the key in the backbuffer now so it shows up if DEBUG_ALWAYSSHOWMAZE<>0 then pokechar mapdata_backbuffer x y 20 12 TILE_KEY return /****************************************************/ remove_gates ; remove gates - TODO flashing effect ; maybe also only remove them when player touches them... playsfx sfx_level2_tune1 for y=1 to 10 for x=1 to 18 z = peekchar(mapdata_rawmap,x,y, 20, 12) if z <> TILE_GATE then goto remove_gates_nextx ; at some point we need to store these locations, or put a new kind of tile here ; so that we'll know when the player reaches the exit pokechar mapdata_rawmap x y 20 12 TILE_STAIRS_UP pokechar mapdata_backbuffer x y 20 12 TILE_STAIRS_UP remove_gates_nextx next next force_refresh=1 return /****************************************************/ play_bkgd_music ;' if we've finished playing our current frame, then get out if cur_music_frame=0 then goto play_bkgd_music_newframe if (frame&$f)=0 then cur_music_frame = cur_music_frame - 1 ; 'frames, sfx, pitch ;data music_level0 goto play_bkgd_music_return play_bkgd_music_newframe z=0 ; 'position within the data ; 3 values per note - #frames, sfx, pitch cur_music_note = cur_music_note + 1 ; go to the next note z = cur_music_note*3 if z >= music_ptr_len then z=0 : cur_music_note=0 play_bkgd_music_play_note z = cur_music_note*3 ; find which note we're on cur_music_frame=music_ptr_lo[[z]] : z=z+1 ; frames t1=music_ptr_lo[[z]] : z=z+1 ; which sfx t2=music_ptr_lo[[z]] : z=z+1 ; pitch if t1=BKGD_SFX_ECHO1 then playsfx sfx_echo1 t2 if t1=BKGD_SFX_TOM1 then playsfx sfx_tom1 t2 if t1=BKGD_SFX_TOM2 then playsfx sfx_tom2 t2 if t1=BKGD_SFX_ECHO2 then playsfx sfx_echo2 t2 if t1=BKGD_SFX_ECHO3 then playsfx sfx_echo3 t2 if t1=BKGD_SFX_ECHO4 then playsfx sfx_echo4 t2 if t1=BKGD_SFX_L2_TUNE1 then playsfx sfx_level2_tune1 t2 if t1=BKGD_SFX_L2_TUNE2 then playsfx sfx_level2_tune2 t2 if t1=BKGD_SFX_L2_TUNE3 then playsfx sfx_level2_tune3 t2 if t1=BKGD_SFX_POUND1 then playsfx sfx_pound1 t2 if t1=BKGD_SFX_POUND2 then playsfx sfx_pound2 t2 play_bkgd_music_return return check_firebutton ;' TODO: maybe hold down button to burn down torch over time, rather than use it all in one flash... ;' return if the ship already fired a shot and the player is holding the fire button down... if button1_debounce>0 && joy0fire1 then return ;' if the player isn't holding fire, ensure button1_debounce is clear and return... ;' move this above the joy0fire1 check above to do autofire... doesn't play great, though if button1_debounce>0 then button1_debounce=button1_debounce-1:return if !joy0fire1 then button1_debounce=0:return ;' testing new mechanic - if you have a torch, you can burn it up to see the whole screen' if torch_timer=0 then goto check_firebutton_return ;' allow only burning down TORCH_TIMER if torch_timer<=TORCH_TIME then torch_timer=0 else torch_timer=torch_timer-TORCH_TIME showmaze_timer=FLASH_TIME button1_debounce=16 playsfx sfx_fireball check_firebutton_return /*** check that the number of gems is correct t2=0 for y=0 to 11 for x=0 to 19 t1 = peekchar(mapdata_rawmap,x,y, 20, 12) if t1=TILE_GEM then t2=t2+1 next next errorcode=converttobcd(t2) */ return /*******************/ update_screen_shake if shake_timer=0 then return shake_timer=shake_timer-1 ;' 1 to SHAKE_TIME_HIT = low, SHAKE_TIME_HIT to SHAKE_TIME_DYING = med if shake_timer>SHAKE_TIME_HIT then shakescreen med if shake_timer>1 then shakescreen low if shake_timer=0 then shakescreen off return /*******************/ remove_all_enemies for temploop = 0 to MAX_ENEMIES enemy1_health[temploop] = 0 next return /*******************/ check_hero_tile ; assumes tile to check is tempx,tempy ; sets hero_tile and z to the tile value being checked ; clears the tile, adds points, sets item bets, etc if the tile is significant hero_tile = peekchar(currentmapdata,tempx,tempy, 20, 12) temp3=0 ;' should we clear the tile at tempx,tempy? if hero_tile = TILE_COINS then z=hero_tile:score0=score0+5 : temp3=1 if hero_tile = TILE_GOLD then z=hero_tile:score0=score0+25 : temp3=1 if hero_tile = TILE_CHEST_OPEN then z=hero_tile:score0=score0+100 : temp3=1 if hero_tile = TILE_NECKLACE then z=hero_tile:score0=score0+150 : temp3=1 if hero_tile = TILE_CROWN then z=hero_tile:score0=score0+500 : temp3=1 if hero_tile = TILE_CHALICE then z=hero_tile:score0=score0+200 : temp3=1 if hero_tile = TILE_POTION then z=hero_tile:score0=score0+10 : temp3=1 if hero_tile = TILE_MAP then z=hero_tile:extra_item_bits=extra_item_bits|ITEM_BIT_MAP : temp3=1 if hero_tile = TILE_KEY then z=hero_tile:extra_item_bits=extra_item_bits|ITEM_BIT_KEY : temp3=1 ; 'monster maze items if hero_tile = TILE_GEM then z=hero_tile:score0=score0+10 : dots_left = dots_left-1 : temp3=1 if hero_tile = TILE_TORCH then z=hero_tile:score0=score0+50 : temp3=1 if hero_tile = TILE_TORCH then extra_item_bits=extra_item_bits|ITEM_BIT_TORCH : torch_timer=torch_timer+TORCH_TIME if hero_tile = TILE_GARLIC_1 || hero_tile = TILE_GARLIC_2 then z=hero_tile:extra_item_bits=extra_item_bits|ITEM_BIT_GARLIC :temp3=1 if hero_tile = TILE_CROSS then z=hero_tile:extra_item_bits=extra_item_bits|ITEM_BIT_CROSS : temp3=1 if hero_tile = TILE_RING then z=hero_tile:extra_item_bits=extra_item_bits|ITEM_BIT_RING :temp3=1 if hero_tile = TILE_STAIRS || hero_tile = TILE_STAIRS_UP then z=hero_tile: reached_stairs=3 : temp3=1 ; we got an item, remove it from the maze if temp3<>0 then pokechar mapdata_backbuffer tempx tempy 20 12 0 if temp3<>0 then pokechar mapdata_rawmap tempx tempy 20 12 0 ; if you got the final gem, then put a key in the maze errorcode=converttobcd(z) if z = TILE_GEM && dots_left = 0 then gosub place_key ; picking up a key removes the gates (for now) if z = TILE_KEY then gosub remove_gates /* if hero_tile<>TILE_CHEST_CLOSED || (extra_item_bits&ITEM_BIT_KEY)=0 then return ;' at this point we've opened a chest ;'if hero_tile = TILE_CHEST_CLOSED && (extra_item_bits&ITEM_BIT_KEY)<>0 then z=hero_tile:pokechar currentmapdata tempx tempy 20 12 TILE_CHEST_OPEN z=hero_tile temp3=rand&3 if temp3=0 then t1=TILE_GARLIC_1 if temp3=1 then t1=TILE_CROSS if temp3=2 then t1=TILE_TORCH if temp3=3 then t1=TILE_RING ;' save this so we can come back to it ;room_item_list[current_room_number]=t1 pokechar currentmapdata tempx tempy 20 12 t1 */ return /*******************/ set_hero_curtile hero_curtilex = (hero_xpos) / 8 hero_curtiley = (hero_ypos) / 16 return /*******************/ move_player2 ;errorcode=converttobcd(moving_dir) z=0 ;' existing moves if moving_dir=MOVING_BIT_UP then goto move_player2_moving_up if moving_dir=MOVING_BIT_DOWN then goto move_player2_moving_down if moving_dir=MOVING_BIT_LEFT then goto move_player2_moving_left if moving_dir=MOVING_BIT_RIGHT then goto move_player2_moving_right goto move_player2_checknewmove move_player2_moving_up moving=moving+1 hero_yvel=hero_yvel+hero_yvel_add if CARRY then hero_ypos=hero_ypos-1 ty1 = dest_tiley*16 if hero_ypos <= ty1 then moving_dir=0 : goto move_player2_donemove goto move_player2_return move_player2_moving_down moving=moving+1 hero_yvel=hero_yvel+hero_yvel_add if CARRY then hero_ypos=hero_ypos+1 ty1 = dest_tiley*16 if hero_ypos >= ty1 then moving_dir=0 : goto move_player2_donemove goto move_player2_return move_player2_moving_left moving=moving+1 hero_xvel=hero_xvel+hero_xvel_add if CARRY then hero_xpos=hero_xpos-1 tx1 = dest_tilex*8 if hero_xpos <= tx1 then moving_dir=0 : goto move_player2_donemove goto move_player2_return move_player2_moving_right moving=moving+1 hero_xvel=hero_xvel+hero_xvel_add if CARRY then hero_xpos=hero_xpos+1 tx1 = dest_tilex*8 if hero_xpos >= tx1 then moving_dir=0 : goto move_player2_donemove goto move_player2_return move_player2_checknewmove z = 0 ;' flag saying we found something hero_tile = 0 moving_dir=0 move_player2_movedown if !joy0down then goto move_player2_moveup ; what tile are they going to move to? tempx = hero_curtilex tempy = hero_curtiley+1 ; let's see if it's free z = peekchar(currentmapdata,tempx,tempy, 20, 12) if z>0 && z0 && z0 && z0 && z0 && z<>TILE_CHEST_CLOSED then room_item_list[current_room_number]=255 ;' don't reset the tile if they leave and come back if z=TILE_RING then hero_xvel_add=HERO_XVEL_FAST:hero_yvel_add=HERO_YVEL_FAST ;'if z<>0 then errorcode=converttobcd(z) if z=0 || z0 && t1=0 then t1=1 : playsfx sfx_pickup move_player2_return return /********************/ draw_hero ;' calculate which animation frame to display, based on direction and ;' the walking counter... ;' animate him based on whether he's moving heroframe=(moving/8)&3 x=hero_xpos y=hero_ypos if herodir=HERODIR_UP || herodir=HERODIR_LEFT then plotsprite hero_l1 PAL_HERO x y heroframe if herodir=HERODIR_DOWN || herodir=HERODIR_RIGHT then plotsprite hero_r1 PAL_HERO x y heroframe ; ' don't draw shadows when showing whole maze if DEBUG_ALWAYSSHOWMAZE <> 0 then goto draw_hero_return if showmaze_timer > 0 then goto draw_hero_return ;' draw shadows x = hero_curtilex*8 y = hero_curtiley*16 ;' update shadow palette t1 = (frame/16)&1 if t1=0 then P4C1=$00 : P4C2=$01 : P4C3=$02 if t1=1 then P4C1=$00 : P4C2=$00 : P4C3=$01 ;'if t1=2 then P4C1=$00 : P4C2=$01 : P4C3=$02 ;'if t1=3 then P4C1=$00 : P4C2=$02 : P4C3=$03 tx3=8:ty3=16 if torch_timer>0 || force_refresh<>0 then tx3=16:ty3=32 tempx=x-tx3 tempy=y-ty3 if hero_curtilex>=3 && hero_curtiley>=3 then plotsprite shadow_ul PAL_SHADOW tempx tempy 0 tempx=x+tx3 if hero_curtilex<=15 && hero_curtiley>=3 then plotsprite shadow_ur PAL_SHADOW tempx tempy 0 tempx=x-tx3 tempy=y+ty3 if hero_curtilex>=3 && hero_curtiley<=8 then plotsprite shadow_ll PAL_SHADOW tempx tempy 0 tempx=x+tx3 if hero_curtilex<=15 && hero_curtiley<=8 then plotsprite shadow_lr PAL_SHADOW tempx tempy 0 draw_hero_return return /********************/ set_enemy_ptr_temploop if temploop>MAX_ENEMIES then cur_enemyptr_lo=enemydef_spider_lo:cur_enemyptr_hi=enemydef_spider_hi: cur_enemyptr_len=enemydef_spider_len: return ;' enemy definition - 9 bytes ;' 0. base health ;' 1. damage per frame ;' 2. behavior bits ;' {0-3} basic AI bits ;' {4 | $10} will chase if player close ;' 3,4. xvel, yvel ;' 5. velocity (frames per step) ;' 6. chase velocity (frames per step) ;' 7,8. width (8/16), height (8/16) if enemy1_type[temploop]=ENEMY_SPIDER then cur_enemyptr_lo=enemydef_spider_lo:cur_enemyptr_hi=enemydef_spider_hi: cur_enemyptr_len=enemydef_spider_len if enemy1_type[temploop]=ENEMY_MUMMY then cur_enemyptr_lo=enemydef_mummy_lo:cur_enemyptr_hi=enemydef_mummy_hi: cur_enemyptr_len=enemydef_mummy_len if enemy1_type[temploop]=ENEMY_BAT then cur_enemyptr_lo=enemydef_bat_lo:cur_enemyptr_hi=enemydef_bat_hi: cur_enemyptr_len=enemydef_bat_len if enemy1_type[temploop]=ENEMY_WITCH then cur_enemyptr_lo=enemydef_witch_lo:cur_enemyptr_hi=enemydef_witch_hi: cur_enemyptr_len=enemydef_witch_len return /********************/ check_enemy_spawn rem ** no time has passed, don't try to spawn new enemies yet if next_enemy_spawn_tick > 0 then next_enemy_spawn_tick = next_enemy_spawn_tick-1 : return gosub get_number_of_enemies ;' if we got all the gems, then spawn one boss if dots_left=0 && spawned_boss=0 then goto check_enemy_spawn_add_enemy if temp8 >= MAX_ENEMIES_AT_ONCE then goto check_enemy_spawn_return check_enemy_spawn_add_enemy next_enemy_spawn_tick = 5 ; spawn enemy on opposite side from player if hero_curtilex<=9 && hero_curtiley<5 then x=18:y=9 if hero_curtilex>9 && hero_curtiley<5 then x=1:y=9 if hero_curtilex<=9 && hero_curtiley>=5 then x=18:y=0 if hero_curtilex>9 && hero_curtiley>=5 then x=1:y=0 check_enemy_spawn_check_y y=y+1 if y>10 then y=1 check_enemy_spawn_check_x t1 = peekchar(mapdata_rawmap,x,y, 20, 12) if t1=0 || t1>=TILE_FIRST_ITEM then goto check_enemy_spawn_place x=x+1 if x>18 then x=1:goto check_enemy_spawn_check_y goto check_enemy_spawn_check_x check_enemy_spawn_place for z=0 to MAX_ENEMIES if enemy1_health[z]>0 then goto check_enemy_spawn_place_next enemy1_curtilex[z]=x enemy1_curtiley[z]=y enemy1_desttilex[z]=x enemy1_desttiley[z]=y enemy1_x[z]=x*8 enemy1_y[z]=y*16 enemy1_health[z]=1 if dots_left = 0 then goto check_enemy_spawn_boss check_enemy_spawn_grunt if (dungeon_level&3)=0 then enemy1_type[z]=ENEMY_SPIDER if (dungeon_level&3)=1 then enemy1_type[z]=ENEMY_BAT if (dungeon_level&3)=2 then enemy1_type[z]=ENEMY_SPIDER if (dungeon_level&3)=3 then enemy1_type[z]=ENEMY_BAT goto check_enemy_spawn_return check_enemy_spawn_boss spawned_boss=1 if (dungeon_level&3)=0 then enemy1_type[z]=ENEMY_WITCH if (dungeon_level&3)=1 then enemy1_type[z]=ENEMY_MUMMY if (dungeon_level&3)=2 then enemy1_type[z]=ENEMY_WITCH if (dungeon_level&3)=3 then enemy1_type[z]=ENEMY_MUMMY playsfx sfx_foundgrave goto check_enemy_spawn_return check_enemy_spawn_place_next next check_enemy_spawn_return return /********************/ update_enemies for z=0 to MAX_ENEMIES if enemy1_health[z]=0 then goto update_enemies_next temploop=z gosub set_enemy_ptr_temploop tx3 = cur_enemyptr_lo[[EN_IDX_XVEL]] ty3 = cur_enemyptr_lo[[EN_IDX_YVEL]] ;if (frame&7)>0 then goto update_enemies_next if enemy1_dir[z]=MOVING_BIT_UP then goto update_enemies_moving_up if enemy1_dir[z]=MOVING_BIT_DOWN then goto update_enemies_moving_down if enemy1_dir[z]=MOVING_BIT_LEFT then goto update_enemies_moving_left if enemy1_dir[z]=MOVING_BIT_RIGHT then goto update_enemies_moving_right goto update_enemies_checknewmove update_enemies_moving_up enemy1_vel[z]=enemy1_vel[z]+ty3 if !CARRY then goto update_enemies_check_playerhit enemy1_y[z] = enemy1_y[z] - 1 ty1 = enemy1_desttiley[z]*16 if enemy1_y[z] <= ty1 then enemy1_dir[z]=0 : enemy1_curtiley[z]=enemy1_desttiley[z] goto update_enemies_check_playerhit update_enemies_moving_down enemy1_vel[z]=enemy1_vel[z]+ty3 if !CARRY then goto update_enemies_check_playerhit enemy1_y[z] = enemy1_y[z] + 1 ty1 = enemy1_desttiley[z]*16 if enemy1_y[z] >= ty1 then enemy1_dir[z]=0 : enemy1_curtiley[z]=enemy1_desttiley[z] goto update_enemies_check_playerhit update_enemies_moving_left enemy1_vel[z]=enemy1_vel[z]+tx3 if !CARRY then goto update_enemies_check_playerhit enemy1_x[z] = enemy1_x[z] - 1 tx1 = enemy1_desttilex[z]*8 if enemy1_x[z] <= tx1 then enemy1_dir[z]=0 : enemy1_curtilex[z]=enemy1_desttilex[z] goto update_enemies_check_playerhit update_enemies_moving_right enemy1_vel[z]=enemy1_vel[z]+tx3 if !CARRY then goto update_enemies_check_playerhit enemy1_x[z] = enemy1_x[z] + 1 tx1 = enemy1_desttilex[z]*8 if enemy1_x[z] >= tx1 then enemy1_dir[z]=0 : enemy1_curtilex[z]=enemy1_desttilex[z] goto update_enemies_check_playerhit update_enemies_check_playerhit temp1=hero_xpos-5 temp2=hero_xpos+5 if enemy1_x[z]temp2 then goto update_enemies_next temp1=hero_ypos-6 temp2=hero_ypos+9 if enemy1_y[z]temp2 then goto update_enemies_next ; it's a hit - kill the enemy and do damage enemy1_health[z]=0 ; if a bat hits you, kill the torch if torch_timer>0 then playsfx sfx_advbite if torch_timer>0 then torch_timer=1 : showmaze_timer=12 : goto update_enemies_return ; if you got hit with minimal torch then you're out. num_lives = num_lives-1 if num_lives=0 then game_stage=STAGE_GAMEOVER : goto update_enemies_return ; goto player died playsfx sfx_uhoh showmaze_timer=4 hero_curtilex = 10 hero_curtiley = 5 hero_xpos=hero_curtilex*8 hero_ypos=hero_curtiley*16 gosub set_hero_curtile dest_tilex = hero_curtilex dest_tiley = hero_curtiley hero_prevtilex=255 hero_prevtiley=255 ; this will kill all enemies to reset memset enemy1_health 0 8 goto update_enemies_return update_enemies_checknewmove temploop = 0 ; ' flag saying we found something enemy1_dir[z]=0 tx3 = 0 ; ' enemy can move in these direction (not blocked) ty3 = 0 ; ' override direction ; let's see if down is free tempx = enemy1_curtilex[z] tempy = enemy1_curtiley[z]+1 temploop = peekchar(mapdata_rawmap,tempx,tempy, 20, 12) if temploop=0 || temploop>=TILE_FIRST_ITEM then tx3=tx3|MOVING_BIT_DOWN ; let's see if up is free tempy = enemy1_curtiley[z]-1 temploop = peekchar(mapdata_rawmap,tempx,tempy, 20, 12) if temploop=0 || temploop>=TILE_FIRST_ITEM then tx3=tx3|MOVING_BIT_UP ; let's see if left is free tempx = enemy1_curtilex[z]-1 tempy = enemy1_curtiley[z] temploop = peekchar(mapdata_rawmap,tempx,tempy, 20, 12) if temploop=0 || temploop>=TILE_FIRST_ITEM then tx3=tx3|MOVING_BIT_LEFT ; let's see if right is free tempx = enemy1_curtilex[z]+1 temploop = peekchar(mapdata_rawmap,tempx,tempy, 20, 12) if temploop=0 || temploop>=TILE_FIRST_ITEM then tx3=tx3|MOVING_BIT_RIGHT ; tx2,ty2 is the distance (in tiles) from the hero if hero_curtilex>enemy1_curtilex[z] then tx2=hero_curtilex-enemy1_curtilex[z] else tx2=enemy1_curtilex[z]-hero_curtilex if hero_curtiley>enemy1_curtiley[z] then ty2=hero_curtiley-enemy1_curtiley[z] else ty2=enemy1_curtiley[z]-hero_curtiley ;errorcode=converttobcd(tx2) ;if (tx3&MOVING_BIT_DOWN)<>0 && ty2>tx2 then goto update_enemies_movedown ;if (tx3&MOVING_BIT_UP)<>0 && ty2>tx2 then goto update_enemies_moveup if (tx3&MOVING_BIT_LEFT)<>0 && tx2>ty2 then goto update_enemies_moveleft if (tx3&MOVING_BIT_RIGHT)<>0 && tx2>ty2 then goto update_enemies_moveright update_enemies_movedown if hero_curtileyenemy1_curtiley[z] || (tx3&MOVING_BIT_UP)=0 then goto update_enemies_moveleft update_enemies_moveup2 ; what tile are they going to move to? tempx = enemy1_curtilex[z] tempy = enemy1_curtiley[z]-1 ; it's either empty or an item so start moving down enemy1_dir[z] = MOVING_BIT_UP enemy1_desttilex[z]=tempx enemy1_desttiley[z]=tempy goto update_enemies_next update_enemies_moveleft if hero_curtilex>enemy1_curtilex[z] || (tx3&MOVING_BIT_LEFT)=0 then goto update_enemies_moveright update_enemies_moveleft2 ; what tile are they going to move to? tempx = enemy1_curtilex[z]-1 tempy = enemy1_curtiley[z] ; it's either empty or an item so start moving down enemy1_dir[z] = MOVING_BIT_LEFT enemy1_desttilex[z]=tempx enemy1_desttiley[z]=tempy goto update_enemies_next update_enemies_moveright if hero_curtilex0 then goto update_enemies_moveright2 if temp3=1 && (tx3&MOVING_BIT_LEFT)<>0 then goto update_enemies_moveleft2 if temp3=2 && (tx3&MOVING_BIT_UP)<>0 then goto update_enemies_moveup2 if temp3=3 && (tx3&MOVING_BIT_DOWN)<>0 then goto update_enemies_movedown2 temp3 = temp3+1 temp3 = temp3&3 goto udpate_enemies_randcheck update_enemies_next next update_enemies_return return /********************/ get_number_of_enemies temp8=0 for temp1=0 to MAX_ENEMIES if enemy1_health[temp1]>0 then temp8 = temp8 + 1 next return /********************/ draw_enemies enemy_frame = (frame/8)&3 for temploop=0 to MAX_ENEMIES if enemy1_health[temploop] = 0 then goto draw_enemies_next tempx=enemy1_x[temploop] tempy=enemy1_y[temploop] ; 'shorter enemies move down 4 pixels to center them if enemy1_type[temploop]=ENEMY_SPIDER || enemy1_type[temploop]=ENEMY_BAT then tempy=tempy+4 ;' plotsprite colortest 3 tempx tempy 0 ;' check if they're in torch distance if DEBUG_ALWAYSSHOWMAZE<>0 then goto draw_enemies_draw if tempx > hero_xpos then x = tempx-hero_xpos else x = hero_xpos - tempx if tempy > hero_ypos then y = tempy-hero_ypos else y = hero_ypos - tempy if showmaze_timer>0 then goto draw_enemies_draw if x > 32 || y > 48 then goto draw_enemies_next draw_enemies_draw if enemy1_type[temploop]=ENEMY_SPIDER && enemy1_curtilex[temploop] > enemy1_desttilex[temploop] then enemy_frame = (frame/8)&1 : plotsprite spider_l1 PAL_SPIDER tempx tempy enemy_frame if enemy1_type[temploop]=ENEMY_SPIDER && enemy1_curtilex[temploop] <= enemy1_desttilex[temploop] then enemy_frame = (frame/8)&1 : plotsprite spider_r1 PAL_SPIDER tempx tempy enemy_frame if enemy1_type[temploop]=ENEMY_WITCH && enemy1_curtilex[temploop] > enemy1_desttilex[temploop] then plotsprite witch_l1 PAL_BOSS tempx tempy enemy_frame if enemy1_type[temploop]=ENEMY_WITCH && enemy1_curtilex[temploop] <= enemy1_desttilex[temploop] then plotsprite witch_r1 PAL_BOSS tempx tempy enemy_frame if enemy1_type[temploop]=ENEMY_BAT then enemy_frame = (frame/8)&3: plotsprite bat1 PAL_BAT tempx tempy enemy_frame if enemy1_type[temploop]=ENEMY_MUMMY && enemy1_curtilex[temploop] <= enemy1_desttilex[temploop] then z=(frame/8)&1:plotsprite mummy_r_1c PAL_BOSS tempx tempy z if enemy1_type[temploop]=ENEMY_MUMMY && enemy1_curtilex[temploop] > enemy1_desttilex[temploop] then z=(frame/8)&1:plotsprite mummy_l_1c PAL_BOSS tempx tempy z draw_enemies_next next ;plotsprite drac_r1 4 120 80 0 return /********************/ draw_status ;' draw score0 and health_bcd ;health_bcd=converttobcd(dots_left) health_bcd=converttobcd(num_lives) plotvalue scoredigits_8_wide_centered 2 health_bcd 2 7 0 plotvalue scoredigits_8_wide_centered 2 score0 6 3 11 if DEBUG_SHOWERRORCODE<>0 then goto draw_status_drawerrorcode errorcode=converttobcd(torch_timer) draw_status_drawerrorcode ;if dots_left <= 99 then errorcode=converttobcd(dots_left) plotvalue scoredigits_8_wide_centered 2 errorcode 2 120 11 /* goto draw_status_return draw_status_checkherotile ;' debug for which tile is above the player - used for finding gravestones or other specific tiles tempx=0 : tempy = 0 if DEBUG_CHECKHEROTILE=1 then tempx = (hero_xpos+8)/8 : tempy = (hero_ypos+8)/16 ; 'right if DEBUG_CHECKHEROTILE=2 then tempx = (hero_xpos-1)/8 : tempy = (hero_ypos+8)/16 ; 'left if DEBUG_CHECKHEROTILE=3 then tempx = (hero_xpos+4)/8 : tempy = (hero_ypos+16)/16 ; 'down if DEBUG_CHECKHEROTILE=4 then tempx = (hero_xpos+4)/8 : tempy = (hero_ypos-1)/16 ; 'up hero_tile = peekchar(currentmapdata,tempx,tempy,20, 12) debugroomcode = converttobcd(hero_tile) plotvalue scoredigits_8_wide_centered 2 debugroomcode 2 56 10 goto draw_status_return */ draw_status_return return data sfx_pickup $10,$2C,$01 ; version, priority, frames per chunk $18,$04,$08 ; first chunk of freq,channel,volume data $1E,$04,$08 $18,$04,$08 $1E,$04,$08 $14,$04,$08 $00,$00,$00 end data sfx_openchest $10,$2C,$02 ; version, priority, frames per chunk $15,$04,$08 ; first chunk of freq,channel,volume data $12,$04,$08 $14,$04,$08 $12,$04,$08 $10,$04,$08 $00,$00,$00 end data sfx_gothit $10,$1f,$02 ; version, priority, frames per chunk $06,$03,$06 ; first chunk of freq,channel,volume data $06,$08,$0E $06,$03,$0D $06,$08,$0C $06,$03,$0B $06,$08,$0A $00,$00,$00 end data sfx_cavalry $10,$07,$05 ; version, priority, frames per chunk $1D,$04,$08 ; first chunk of freq,channel,volume data $1A,$04,$08 $17,$04,$08 $13,$04,$08 $17,$04,$08 $13,$04,$08 $13,$04,$08 $00,$00,$00 end data sfx_hitenemy $10,$20,$02 ; version, priority, frames per chunk $0a,$03,$06 ; first chunk of freq,channel,volume data $09,$03,$08 $08,$03,$07 $09,$03,$06 $00,$00,$00 end data sfx_killedenemy1 $10,$05,$01 ; version, priority, frames per chunk $1B,$04,$08 ; first chunk of freq,channel,volume data $1E,$04,$08 $1B,$04,$08 $1E,$04,$08 $18,$04,$08 $00,$00,$00 end data sfx_killedenemy2 $10,$05,$01 ; version, priority, frames per chunk $18,$04,$08 ; first chunk of freq,channel,volume data $1E,$04,$08 $18,$04,$08 $1E,$04,$08 $14,$04,$08 $00,$00,$00 end data sfx_magicbolt $10,$04,$02 ; version, priority, frames per chunk $14,$04,$08 ; first chunk of freq,channel,volume data $16,$04,$07 $18,$04,$06 $1a,$04,$06 $00,$00,$00 end data sfx_arrow $10,$04,$02 ; version, priority, frames per chunk $1a,$04,$06 ; first chunk of freq,channel,volume data $18,$04,$07 $16,$04,$08 $14,$04,$09 $00,$00,$00 end data sfx_arrow_bounce $10,$03,$02 ; version, priority, frames per chunk $20,$04,$08 ; first chunk of freq,channel,volume data $1c,$04,$08 $00,$00,$00 end data sfx_sword $10,$04,$02 ; version, priority, frames per chunk $22,$03,$08 ; first chunk of freq,channel,volume data $23,$03,$08 $24,$03,$08 $25,$03,$08 $26,$03,$08 $00,$00,$00 end data sfx_fireball $18,$04,$03 ; version, priority, frames per chunk $28,$03,$06 ; first chunk of freq,channel,volume data $27,$03,$04 $26,$03,$05 $25,$03,$06 $24,$03,$07 $23,$03,$08 $22,$03,$08 $00,$00,$00 end data sfx_foundgrave $10,$09,$04 ; version, priority, frames per chunk $18,$04,$08 ; first chunk of freq,channel,volume data $1E,$04,$08 $18,$04,$08 $1E,$04,$08 $14,$04,$08 $13,$04,$08 $12,$04,$08 $11,$04,$08 $10,$04,$08 $00,$00,$00 end data sfx_gotomap $10,$04,$02 ; version, priority, frames per chunk $00,$06,$05 ; first chunk of freq,channel,volume data $01,$06,$02 $02,$06,$01 $03,$06,$01 $00,$00,$00 end data sfx_stairs $10,$10,$00 ; version, priority, frames per chunk $0d,$0c,$0f ; first chunk of freq,channel,volume $0d,$0c,$0d $10,$0c,$0b $10,$0c,$0f $1e,$0c,$06 $0e,$0c,$05 $0e,$0c,$0c $12,$0c,$0f $12,$0c,$0d $10,$0c,$0f $0e,$0c,$0f $0d,$0c,$0f $12,$0c,$0a $07,$06,$0b $1e,$0c,$07 $10,$0c,$0f $10,$0c,$0e $0e,$0c,$0d $17,$0c,$07 $07,$06,$08 $1e,$0c,$07 $10,$0c,$08 $0e,$0c,$0a $0d,$0c,$0d $0d,$0c,$06 $1e,$0c,$05 $1c,$04,$03 $0d,$0c,$08 $0c,$0c,$0b $0c,$0c,$06 $0e,$0c,$08 $1b,$0c,$04 $0c,$0c,$0a $0c,$0c,$03 $0a,$0c,$07 $0d,$0c,$04 $0d,$0c,$07 $0b,$0c,$05 $0a,$0c,$05 $1e,$04,$03 $00,$00,$00 end data sfx_coin $10,$10,$00 ; version, priority, frames per chunk $04,$0c,$0f ; first chunk of freq,channel,volume $04,$0c,$0f $0a,$04,$0e $0a,$04,$0f $0a,$04,$0f $0a,$04,$0d $0a,$04,$09 $0a,$04,$09 $0a,$04,$08 $0a,$04,$07 $0a,$04,$06 $0a,$04,$05 $0a,$04,$03 $0a,$04,$07 $0a,$04,$09 $0a,$04,$03 $0a,$04,$01 $0a,$04,$01 $0a,$04,$01 $0a,$04,$00 $0a,$04,$01 $0a,$04,$01 $0a,$04,$01 $00,$00,$00 end data sfx_advbite $10,$10,$02 ; version, priority, frames per chunk $1F,$03,$0F ; first chunk of freq,channel,volume data $1F,$08,$0E $1F,$03,$0D $1F,$08,$0C $1F,$03,$0B $1F,$08,$0A $1F,$03,$09 $1F,$08,$08 $1F,$03,$07 $1F,$08,$06 $1F,$03,$05 $1F,$08,$04 $1F,$03,$03 $1F,$08,$02 $1F,$03,$01 $00,$00,$00 end data sfx_powerup $10,$10,$00 ; version, priority, frames per chunk $1e,$06,$0f ; first chunk of freq,channel,volume $1c,$04,$0f $0c,$0c,$0f $0c,$0c,$0f $0c,$0c,$0f $1c,$04,$0f $1b,$04,$0a $16,$04,$09 $12,$04,$07 $12,$04,$0e $12,$04,$08 $0d,$04,$03 $12,$04,$08 $12,$04,$0f $0b,$0c,$0f $0b,$0c,$0f $0b,$0c,$0c $1c,$04,$06 $1c,$04,$0c $07,$0c,$0f $07,$0c,$09 $05,$0c,$0a $18,$04,$07 $07,$0c,$0f $07,$0c,$0a $05,$0c,$0c $05,$0c,$05 $1e,$06,$03 $03,$0c,$04 $03,$0c,$04 $03,$0c,$04 $02,$0c,$08 $03,$0c,$04 $1e,$06,$02 $0a,$0c,$0e $0a,$0c,$0f $1e,$04,$0d $19,$04,$08 $15,$04,$0b $15,$04,$0f $15,$04,$08 $0f,$04,$07 $15,$04,$07 $15,$04,$0c $06,$0c,$07 $0f,$04,$02 $00,$06,$04 $01,$0c,$00 $0a,$04,$04 $0a,$04,$08 $0a,$04,$03 $07,$04,$03 $0a,$04,$03 $00,$00,$00 end data sfx_pound1 $10,$10,$00 ; version, priority, frames per chunk $0f,$06,$0a ; first chunk of freq,channel,volume $1e,$0c,$0b $0f,$06,$0b $07,$06,$07 $0f,$06,$0b $0f,$06,$09 $07,$06,$07 $1e,$06,$04 $0a,$06,$03 $0a,$06,$03 $1e,$06,$02 $0f,$06,$01 $00,$00,$00 end data sfx_pound2 $10,$10,$00 ; version, priority, frames per chunk $0f,$06,$0e ; first chunk of freq,channel,volume $1c,$0c,$0e $0d,$06,$0e $05,$06,$0a $0d,$06,$0e $07,$06,$08 $0d,$06,$07 $08,$06,$07 $0d,$06,$06 $0e,$06,$02 $00,$00,$00 end data sfx_tom1 $10,$10,$00 ; version, priority, frames per chunk $19,$06,$04 ; first chunk of freq,channel,volume $0b,$0e,$04 $1a,$06,$08 $18,$0f,$0f $15,$0f,$0f $1e,$0c,$0f $1e,$0c,$0f $1e,$0c,$0f $10,$0f,$0f $12,$0f,$0f $1e,$0c,$0c $1e,$0c,$08 $1e,$0c,$08 $1e,$0c,$04 $1e,$0c,$04 $06,$06,$04 $00,$00,$00 end data sfx_tom2 $10,$10,$00 ; version, priority, frames per chunk $19,$06,$02 ; first chunk of freq,channel,volume $0b,$0e,$02 $1a,$06,$06 $18,$0f,$0d $15,$0f,$0d $1e,$0c,$0d $1e,$0c,$0d $1e,$0c,$0d $10,$0f,$0d $12,$0f,$0d $1e,$0c,$0a $1e,$0c,$06 $1e,$0c,$06 $1e,$0c,$02 $1e,$0c,$02 $06,$06,$02 $00,$00,$00 end data sfx_level2_tune1 $10,$08,$10 ; version, priority, frames per chunk $10,$06,$08 ; first chunk of freq,channel,volume data $11,$06,$07 $10,$06,$06 $09,$06,$05 $08,$06,$04 $08,$06,$02 $00,$00,$00 end data sfx_level2_tune2 $12,$08,$10 ; version, priority, frames per chunk $0b,$06,$08 ; first chunk of freq,channel,volume data $13,$06,$07 $0c,$06,$06 $14,$06,$07 $0d,$06,$06 $15,$06,$06 $0e,$06,$05 $16,$06,$05 $0f,$06,$04 $17,$06,$04 $10,$06,$03 $18,$06,$03 $11,$06,$02 $19,$06,$01 $12,$06,$01 $00,$00,$00 end data sfx_level2_tune3 $10,$08,$10 ; version, priority, frames per chunk $09,$06,$08 ; first chunk of freq,channel,volume data $10,$06,$07 $09,$06,$06 $11,$06,$07 $0a,$06,$06 $12,$06,$06 $0b,$06,$05 $13,$06,$05 $0c,$06,$04 $14,$06,$04 $0d,$06,$03 $15,$06,$03 $0e,$06,$02 $16,$06,$01 $0f,$06,$01 $00,$00,$00 end data sfx_echo1 ; 'basic echo sfx $10,$08,$08 ; version, priority, frames per chunk $18,$06,$07 ; first chunk of freq,channel,volume data $08,$06,$07 $01,$00,$00 $18,$06,$03 $08,$06,$03 $01,$00,$00 $18,$06,$01 $08,$06,$01 $00,$00,$00 end data sfx_echo2 ; 'slower, lower-pitched echo $10,$08,$0a ; version, priority, frames per chunk $1a,$06,$07 ; first chunk of freq,channel,volume data $12,$06,$07 $01,$00,$00 $1c,$06,$03 $14,$06,$03 $01,$00,$00 $18,$06,$01 $10,$06,$01 $00,$00,$00 end data sfx_echo3 ; 'longer echo $10,$08,$0a ; version, priority, frames per chunk $18,$06,$07 ; first chunk of freq,channel,volume data $10,$06,$07 $01,$00,$00 $19,$06,$05 $11,$06,$05 $01,$00,$00 $1a,$06,$03 $12,$06,$03 $01,$00,$00 $1b,$06,$02 $13,$06,$02 $00,$00,$00 end data sfx_echo4 ; 'slower, lower-pitched echo $10,$08,$0a ; version, priority, frames per chunk $12,$06,$07 ; first chunk of freq,channel,volume data $1a,$06,$07 $01,$00,$00 $14,$06,$03 $1c,$06,$03 $01,$00,$00 $10,$06,$01 $18,$06,$01 $00,$00,$00 end data sfx_dropmedium $10,$10,$00 ; version, priority, frames per chunk $00,$04,$00 ; first chunk of freq,channel,volume $03,$06,$0c $0d,$0c,$0f $1b,$04,$04 $06,$0c,$00 $00,$06,$00 $07,$06,$00 $10,$0c,$00 $0d,$0c,$00 $10,$0c,$00 $03,$06,$00 $10,$0c,$00 $1b,$04,$00 $10,$0c,$00 $10,$0c,$00 $03,$06,$00 $00,$00,$00 end data sfx_uhoh $10,$10,$00 ; version, priority, frames per chunk $07,$06,$01 ; first chunk of freq,channel,volume $1e,$0c,$03 $1e,$0c,$04 $17,$0c,$04 $0a,$06,$06 $0a,$0c,$0a $07,$06,$0f $1e,$04,$0f $19,$04,$0f $19,$04,$0f $1b,$04,$07 $18,$04,$07 $18,$04,$04 $07,$0c,$02 $16,$04,$00 $16,$04,$00 $16,$04,$00 $0f,$06,$00 $1e,$06,$00 $1e,$06,$00 $1e,$06,$00 $19,$04,$00 $1e,$04,$01 $1e,$04,$0a $1c,$04,$0f $1c,$04,$0f $1e,$04,$0f $1b,$0c,$0f $0d,$0c,$0f $0d,$0c,$0e $0e,$0c,$0f $0e,$0c,$0f $0e,$0c,$0f $0e,$0c,$0f $0e,$0c,$0f $0e,$0c,$0d $1b,$0c,$0a $04,$0c,$0a $1b,$0c,$0b $0e,$0c,$0a $0e,$0c,$0a $1b,$0c,$0a $0d,$0c,$0a $0d,$0c,$06 $0e,$0c,$04 $0e,$0c,$04 $0e,$0c,$02 $00,$00,$00 end alphachars ' abcdefghijklmnopqrstuvwxyz' alphadata screenmap_level1 tileset_test 'qrrsmmmmmmmmmmmtuvwx' 'mg gm' 'm mmmnnmmn mmnnnm m' 'm nnmmmnm m m' 'm m m m m m' 'm mnnn nm n nmnmn m' 'm n m' 'mmmmmn cefc m nnmm' 'm aabb n m' 'm nmm addb mm m' 'mg m m gm' 'qrrrrrsmmmmmmqrrrrrs' end alphadata screenmap_level2 tileset_test 'qrrshhhhhhhhhhhtuvwx' 'mg cefc gm' 'm kkl j aabb llkll m' 'm m j addb m' 'm m in kklkk m' 'm m nmn m m' 'm jkj mlmkmlm m' 'm l j jj m' 'm l lj j i j m' 'm ki j nn m m m' 'mg lkl l gm' 'qrrrrrshhhhhhqrrrrrs' end