1 votes
Source Code
Download .dasm16 file |;;;;;;;;;;;;;;;;;;;;;; ; Soron's Snake - v2 ; ;;;;;;;;;;;;;;;;;;;;;; ; coded by Soron of http://0x10cforum.com/, for the DCPU ; hereby released into the public domain ; (or use the Unlicense, CC0, etc., if your country doesn't have public domain) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Now conforms to the ABI! No longer clobbers your registers! ; ; Just be sure to "SET PC, exit_snake" when you want to exit ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; targetted for the DCPU-16 Studio assembler/emulator ; may or may not work for other emulators, since I/O hasn't been made official ; the snake is drawn on the background, and the food on the foreground ; suggested tweaks: ; adjust sleep_duration to speed up/slow down the game ; adjust the upper nybble of food_char to change food color ; adjust the lower byte of food_char to change food shape ; adjust prng_dat to start with a different RNG seed ; if you're not using a 32x16 window, adjust assorted things to not break ; (things such as dat_width and dat_height, up_dir and down_dir, etc.) ; this could also probably be made more efficient, but, uh... not a priority, ; given that we're looping 0x1000 times just to slow things down! ; directions: ; 0x0001 = right ; 0x0020 = down (assuming a 32 char-width screen) ; 0xFFFF = left ; 0xFFE0 = up ; up/down WILL need to be changed if you use a different-width screen ; how registers, etc., are used: ; A = head position ; B = direction ; C = food position ; X = position of thing to draw on screen, etc ; Y = position of last segment touched ; Z = temporary data storage, for assorted calculations ; I = for loops and other iterations ; J = address of the stack element which stores the pos of start of tail ; SP = address of the stack element which stores the pos of end of tail ; O = not used. Why would you use this for Snake? What sort of madman ARE you? :snake_init ;conform to the ABI by not clobbering ALL the registers SET PUSH, X SET PUSH, Y SET PUSH, Z SET PUSH, I SET PUSH, J SET J, SP ; keep track of where OUR stack starts JSR clear_screen SET A, 0x0001 ; head position (add 0x8000 to get screen pos) SET B, 0x0001 ; direction JSR gen_food SET PUSH, 0x0000 ; start of tail position BOR [0x8000], [tail_color] BOR [0x8001], [head_color] :game_loop JSR sleep IFE [0x9000], [up_key] SET PC, turn_up IFE [0x9000], [down_key] SET PC, turn_down IFE [0x9000], [left_key] SET PC, turn_left IFE [0x9000], [right_key] SET PC, turn_right :move_snake SET [0x9000], 0 SET Y, A ADD A, B ; yay overflow ^_^! SET X, A :check_collision SET Z, [dat_width] MUL Z, [dat_height] IFG X, Z ; went off the screen somehow SET PC, lose_game SET Z, X ADD Z, 0x8000 IFE [Z], [tail_color] ; hit the tail! SET PC, lose_game IFE B, [dir_left] SET PC, check_edge_collision IFE B, [dir_right] SET PC, check_edge_collision SET PC, draw_snake :check_edge_collision ;change this next block if you changed screen width SET X, A AND X, 0xFFE0 SET Z, Y AND Z, 0xFFE0 IFN X, Z SET PC, lose_game ; we have gone off the left/right edge! SET X, A :draw_snake ADD X, 0x8000 BOR [X], [head_color] SET I, J :tail_loop SUB I, 1 IFG SP, I SET PC, finish_tail SET Z, [I] SET [I], Y SET Y, Z SET X, [I] ADD X, 0x8000 BOR [X], [tail_color] SET PC, tail_loop :turn_left IFN B, [dir_right] SET B, [dir_left] SET PC, move_snake :turn_right IFN B, [dir_left] SET B, [dir_right] SET PC, move_snake :turn_up IFN B, [dir_down] SET B, [dir_up] SET PC, move_snake :turn_down IFN B, [dir_up] SET B, [dir_down] SET PC, move_snake :finish_tail IFE A, C SET PC, grow_tail SET X, Y ADD X, 0x8000 AND [X], 0xF0FF SET PC, game_loop :grow_tail SET PUSH, Y SET X, C ADD X, 0x8000 AND [X], 0x0F00 ; make sure to clear the old food item! JSR gen_food SET PC, game_loop :gen_food JSR rand SET C, [prng_dat] SET Z, [dat_width] MUL Z, [dat_height] MOD C, Z SET X, C ADD X, 0x8000 BOR [X], [food_char] SET PC, POP :lose_game SET PC, snake_init :exit_snake SET SP, J SET J, POP SET I, POP SET Z, POP SET Y, POP SET X, POP SET PC, POP :sleep SET I, 0 :sleep_loop ADD I, 1 IFG I, [sleep_duration] SET PC, POP SET PC, sleep_loop :sleep_duration DAT 0x1000 :clear_screen SET A, SP SET SP, 0x8000 :clear_screen_loop SET POP, 0 IFG SP, 0x8200 SET PC, clear_screen_exit SET PC, clear_screen_loop :clear_screen_exit SET SP, A SET PC, POP :rand ;introduce at least a LITTLE unpredictability MUL [prng_dat], A ADD [prng_dat], SP ;now do the actual work MUL [prng_dat], 31421 ADD [prng_dat], 6927 SET PC, POP :prng_dat DAT 0x13AD ; a reasonable start value ;if you change width, you WILL need to double-check edge-of-screen collision :dat_width DAT 32 :dat_height DAT 16 :head_color DAT 0x0700 :tail_color DAT 0x0F00 :food_char DAT 0xC040 ; "@" char, for all y'all roguelike fans :) :dir_right DAT 0x0001 :dir_down DAT 0x0020 ; relies on screen width :dir_left DAT 0xFFFF :dir_up DAT 0xFFE0 ; relies on screen width :up_key DAT 0x0003 :down_key DAT 0x0004 :left_key DAT 0x0001 :right_key DAT 0x0002

Comments
Sign in to comment and vote
No comments yet