sd:rogueima_i_mvp-4
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| sd:rogueima_i_mvp-4 [2026/05/09 16:06] – appledog | sd:rogueima_i_mvp-4 [2026/05/10 16:47] (current) – appledog | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| = Rogueima I MPV-4 | = Rogueima I MPV-4 | ||
| - | * rogueima.asm: | + | * rogueima.asm: |
| - | * draw.asm: | + | * draw.asm: |
| - | * map.asm: | + | * map.asm: |
| * mon.asm: 99 | * mon.asm: 99 | ||
| * msg.asm: 166 | * msg.asm: 166 | ||
| - | * obj.asm: | + | * obj.asm: |
| * talk.asm: 166 | * talk.asm: 166 | ||
| + | * combat.asm: 149 | ||
| - | | + | Total: 1,385 SLOC. According to SLOCCOUNT, a program by David A. Wheeler, using traditional software development metrics this program would have taken four months and cost $38,033 to develop. The four months is about right, then again I did this in about 2 months; and frankly, I would have done it for half the cost! |
| - | Development Effort Estimate, Person-Years (Person-Months) = 0.25 (3.01) | + | |
| - | | + | |
| - | Schedule Estimate, Years (Months) | + | |
| - | | + | |
| - | Estimated Average Number of Developers (Effort/ | + | |
| - | Total Estimated Cost to Develop | + | |
| - | | + | |
| == rogueima.sda | == rogueima.sda | ||
| Line 91: | Line 85: | ||
| CALL @draw_map | CALL @draw_map | ||
| CALL @get_input | CALL @get_input | ||
| - | CALL @move_mobs | ||
| - | ;CALL @robot_beep | ||
| CALL @inc_game_time | CALL @inc_game_time | ||
| Line 244: | Line 236: | ||
| RET | RET | ||
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| - | ;; Move the robot. | ||
| - | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| - | move_mobs: | ||
| - | RET | ||
| ;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;; | ||
| Line 289: | Line 276: | ||
| POP ELM ; destroy return address of CALL from main loop | POP ELM ; destroy return address of CALL from main loop | ||
| RET ; exit program. | RET ; exit program. | ||
| - | |||
| - | robot_beep: | ||
| - | LDELM @robot_sfx | ||
| - | LDAH $52 | ||
| - | INT $11 | ||
| - | RET | ||
| ; ============================================================================ | ; ============================================================================ | ||
| Line 305: | Line 286: | ||
| msg_quit: | msg_quit: | ||
| .bytes "QUIT GAME", 10,13,0 | .bytes "QUIT GAME", 10,13,0 | ||
| + | msg_died: | ||
| + | .bytes "You died.", | ||
| robot_sfx: | robot_sfx: | ||
| .bytes "T120 W1 V5 O2 L24 B", 0 | .bytes "T120 W1 V5 O2 L24 B", 0 | ||
| Line 600: | Line 583: | ||
| CALL @draw_world | CALL @draw_world | ||
| CALL @draw_items | CALL @draw_items | ||
| - | CALL @draw_player | + | CALL @move_mon |
| CALL @draw_mobs | CALL @draw_mobs | ||
| + | CALL @draw_player | ||
| CALL @draw_stats | CALL @draw_stats | ||
| CALL @draw_msgs | CALL @draw_msgs | ||
| Line 608: | Line 592: | ||
| LDAH $50 ; VSTART | LDAH $50 ; VSTART | ||
| INT 0x18 | INT 0x18 | ||
| + | |||
| + | LDA [@player_hp] | ||
| + | CMP A, 0 | ||
| + | JZ @kill_player | ||
| RET | RET | ||
| Line 682: | Line 670: | ||
| RET | RET | ||
| + | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| + | ;; Draw all the monsters that are placed on the map. | ||
| + | ;; Filters on OBJ_TYPE == 2 (monster), skips items. | ||
| + | ;; | ||
| draw_mobs: | draw_mobs: | ||
| - | ; stub for now | + | |
| + | LDT [@disp_dim] | ||
| + | LDELM @OBJS_BASE | ||
| + | draw_mobs_loop: | ||
| + | LDELM [ELM] | ||
| + | CMP ELM, @OBJS_BASE | ||
| + | JZ @draw_mobs_done | ||
| + | |||
| + | LDI @OBJ_ID | ||
| + | LDA [ELM+I] | ||
| + | JZ @draw_mobs_loop | ||
| + | |||
| + | LDI @OBJ_TYPE | ||
| + | LDA [ELM+I] | ||
| + | CMP A, #2 ; OBJ_TYPE_MONSTER | ||
| + | JNZ @draw_mobs_loop | ||
| + | |||
| + | LDI @OBJ_X | ||
| + | LDX [ELM+I] | ||
| + | LDI @OBJ_Y | ||
| + | LDY [ELM+I] | ||
| + | |||
| + | ; --- Visibility: is (XL, YL) inside the viewport? --- | ||
| + | CMP XL, DL | ||
| + | JNC @draw_mobs_loop | ||
| + | MOV AL, DL | ||
| + | ADD AL, TL | ||
| + | CMP XL, AL | ||
| + | JC @draw_mobs_loop | ||
| + | |||
| + | CMP YL, DH | ||
| + | JNC @draw_mobs_loop | ||
| + | MOV AL, DH | ||
| + | ADD AL, TH | ||
| + | CMP YL, AL | ||
| + | JC @draw_mobs_loop | ||
| + | |||
| + | ; --- Map → screen --- | ||
| + | SUB XL, DL | ||
| + | ADD XL, #1 ; play_x_offset | ||
| + | SUB YL, DH | ||
| + | ADD YL, #1 ; play_y_offset | ||
| + | |||
| + | ; --- Draw --- | ||
| + | LDI @OBJ_VIS | ||
| + | LDBL [ELM+I] | ||
| + | LDAH $11 | ||
| + | INT $10 | ||
| + | JMP @draw_mobs_loop | ||
| + | draw_mobs_done: | ||
| RET | RET | ||
| Line 1067: | Line 1108: | ||
| STAL [ELM+I] | STAL [ELM+I] | ||
| RET | RET | ||
| - | </ | + | |
| + | |||
| + | ;;;;;;;;;;;;;;;;;; | ||
| + | ;; has_mon(x, | ||
| + | ;; | ||
| + | ;; Returns CARRY SET if monster. | ||
| + | ;; Returns monster pointer in FLD. | ||
| + | ;; | ||
| + | has_mon: | ||
| + | PUSH I | ||
| + | PUSH B | ||
| + | |||
| + | LDFLD @OBJS_BASE | ||
| + | has_mon_loop: | ||
| + | LDFLD [FLD] | ||
| + | CMP FLD, @OBJS_BASE | ||
| + | JZ @has_mon_no | ||
| + | |||
| + | LDI @OBJ_ID | ||
| + | LDB [FLD+I] | ||
| + | JZ @has_mon_loop | ||
| + | |||
| + | LDI @OBJ_TYPE | ||
| + | LDB [FLD+I] | ||
| + | CMP B, #2 ; OBJ_TYPE_MONSTER | ||
| + | JNZ @has_mon_loop | ||
| + | |||
| + | LDI @OBJ_X | ||
| + | LDBL [FLD+I] | ||
| + | CMP BL, XL | ||
| + | JNZ @has_mon_loop | ||
| + | |||
| + | LDI @OBJ_Y | ||
| + | LDBL [FLD+I] | ||
| + | CMP BL, YL | ||
| + | JNZ @has_mon_loop | ||
| + | |||
| + | ; Match returns pointer in FLD, CF=1 | ||
| + | SEC | ||
| + | JMP @has_mon_done | ||
| + | |||
| + | has_mon_no: | ||
| + | CLC ; no monster; FLD unchanged. | ||
| + | |||
| + | has_mon_done: | ||
| + | POP B | ||
| + | POP I | ||
| + | RET | ||
| + | |||
| + | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| + | ;; move_mon | ||
| + | ;; | ||
| + | ;; Attempt to move every live monster | ||
| + | ;; towards the player | ||
| + | ;; | ||
| + | move_mon: | ||
| + | LDELM @OBJS_BASE | ||
| + | move_mon_loop: | ||
| + | LDELM [ELM] | ||
| + | CMP ELM, @OBJS_BASE | ||
| + | JZ @move_mon_done | ||
| + | |||
| + | ; live monsters only | ||
| + | LDI @OBJ_ID | ||
| + | LDA [ELM+I] | ||
| + | JZ @move_mon_loop | ||
| + | LDI @OBJ_TYPE | ||
| + | LDA [ELM+I] | ||
| + | CMP A, #2 ; OBJ_TYPE_MONSTER | ||
| + | JNZ @move_mon_loop | ||
| + | |||
| + | LDI @OBJ_X | ||
| + | LDXL [ELM+I] | ||
| + | LDI @OBJ_Y | ||
| + | LDYL [ELM+I] | ||
| + | |||
| + | ; sign(PX - mx) to CL | ||
| + | LDAL [@PX] | ||
| + | CMP AL, XL | ||
| + | JZ @mm_dx_zero | ||
| + | JC @mm_dx_pos | ||
| + | LDCL #$FF ; PX < mx, step left | ||
| + | JMP @mm_dx_done | ||
| + | |||
| + | mm_dx_pos: | ||
| + | LDCL #$01 | ||
| + | JMP @mm_dx_done | ||
| + | |||
| + | mm_dx_zero: | ||
| + | LDCL #$00 | ||
| + | |||
| + | mm_dx_done: | ||
| + | LDAL [@PY] | ||
| + | CMP AL, YL | ||
| + | JZ @mm_dy_zero | ||
| + | JC @mm_dy_pos | ||
| + | LDDL #$FF | ||
| + | JMP @mm_dy_done | ||
| + | |||
| + | mm_dy_pos: | ||
| + | LDDL #$01 | ||
| + | JMP @mm_dy_done | ||
| + | |||
| + | mm_dy_zero: | ||
| + | LDDL #$00 | ||
| + | |||
| + | mm_dy_done: | ||
| + | ; Pick axis | ||
| + | CMP CL, #0 | ||
| + | JNZ @mm_dx_nz | ||
| + | CMP DL, #0 | ||
| + | JZ @move_mon_loop | ||
| + | JMP @mm_use_y | ||
| + | |||
| + | mm_dx_nz: | ||
| + | CMP DL, #0 | ||
| + | JZ @mm_use_x | ||
| + | |||
| + | ; Both non-zero; coin flip | ||
| + | LDAH $00 | ||
| + | INT 0x13 | ||
| + | MOD B, #2 | ||
| + | CMP B, #0 | ||
| + | JZ @mm_use_x | ||
| + | ; fall through to mm_use_y | ||
| + | |||
| + | mm_use_y: | ||
| + | ADD YL, DL ; YL = my + sign(dy) | ||
| + | JMP @mm_check | ||
| + | |||
| + | mm_use_x: | ||
| + | ADD XL, CL ; XL = mx + sign(dx) | ||
| + | |||
| + | mm_check: | ||
| + | LDAL [@PX] | ||
| + | CMP AL, XL | ||
| + | JNZ @mm_check_obj | ||
| + | LDAL [@PY] | ||
| + | CMP AL, YL | ||
| + | JNZ @mm_check_obj | ||
| + | |||
| + | ; Target tile IS the player, so attack instead of move | ||
| + | LDFLD @player_obj | ||
| + | |||
| + | CALL @do_combat | ||
| + | JMP @move_mon_loop | ||
| + | |||
| + | mm_check_obj: | ||
| + | PUSH ELM | ||
| + | CALL @has_mon | ||
| + | JC @mm_pop_skip | ||
| + | CALL @is_walkable | ||
| + | JNC @mm_pop_skip | ||
| + | |||
| + | ; commit the move | ||
| + | POP ELM | ||
| + | SED | ||
| + | LDI @OBJ_X | ||
| + | STXL [ELM+I] | ||
| + | LDI @OBJ_Y | ||
| + | STYL [ELM+I] | ||
| + | CLD | ||
| + | JMP @move_mon_loop | ||
| + | |||
| + | mm_pop_skip: | ||
| + | POP ELM | ||
| + | JMP @move_mon_loop | ||
| + | |||
| + | move_mon_done: | ||
| + | RET</ | ||
| == msg.sda | == msg.sda | ||
| Line 1478: | Line 1688: | ||
| LDA [ELM+I] | LDA [ELM+I] | ||
| JZ @draw_items_loop | JZ @draw_items_loop | ||
| + | |||
| + | LDI @OBJ_TYPE | ||
| + | LDA [ELM+I] | ||
| + | CMP A, #1 ; OBJ_TYPE_GOLD — this filter is the fix | ||
| + | JNZ @draw_items_loop | ||
| LDI @OBJ_X | LDI @OBJ_X | ||
| Line 1795: | Line 2010: | ||
| </ | </ | ||
| + | == combat.sda | ||
| + | <codify armasm> | ||
| + | player_obj: | ||
| + | ; 40 bytes, about sizeof(OBJ) | ||
| + | .bytes 0, | ||
| + | .bytes 0, | ||
| + | .bytes 0, | ||
| + | .bytes 0, | ||
| + | |||
| + | str_you: | ||
| + | .bytes "You ", 0 | ||
| + | str_the: | ||
| + | .bytes "The ", 0 | ||
| + | str_attack: | ||
| + | .bytes " | ||
| + | str_attacks: | ||
| + | .bytes " | ||
| + | str_rat: | ||
| + | .bytes "rat ", 0 | ||
| + | str_snake: | ||
| + | .bytes "snake ", 0 | ||
| + | str_spider: | ||
| + | .bytes " | ||
| + | str_unknown: | ||
| + | .bytes "thing ", 0 | ||
| + | str_dies: | ||
| + | .bytes " | ||
| + | str_you_die: | ||
| + | .bytes "You die!", 13, 10, 0 | ||
| + | |||
| + | copy_player_to_obj: | ||
| + | PUSH ELM | ||
| + | PUSH A | ||
| + | PUSH I | ||
| + | |||
| + | LDELM @player_obj | ||
| + | |||
| + | LDI @OBJ_DATA1 | ||
| + | LDA [@player_hp] | ||
| + | STA [ELM+I] | ||
| + | |||
| + | LDI @OBJ_DATA2 | ||
| + | LDA [@player_str] | ||
| + | STA [ELM+I] | ||
| + | |||
| + | POP I | ||
| + | POP A | ||
| + | POP ELM | ||
| + | RET | ||
| + | |||
| + | copy_obj_to_player: | ||
| + | PUSH ELM | ||
| + | PUSH A | ||
| + | PUSH I | ||
| + | LDELM @player_obj | ||
| + | |||
| + | LDI @OBJ_DATA1 | ||
| + | LDA [ELM+I] | ||
| + | STA [@player_hp] | ||
| + | |||
| + | LDI @OBJ_DATA2 | ||
| + | LDA [ELM+I] | ||
| + | STA [@player_str] | ||
| + | POP I | ||
| + | POP A | ||
| + | POP ELM | ||
| + | RET | ||
| + | |||
| + | print_mon_name: | ||
| + | PUSH ELM | ||
| + | PUSH A | ||
| + | PUSH I | ||
| + | LDI @OBJ_VIS | ||
| + | LDAL [ELM+I] | ||
| + | CMP AL, #' | ||
| + | JZ @pmn_rat | ||
| + | CMP AL, #' | ||
| + | JZ @pmn_snake | ||
| + | CMP AL, #' | ||
| + | JZ @pmn_spider | ||
| + | LDELM @str_unknown | ||
| + | JMP @pmn_emit | ||
| + | pmn_rat: | ||
| + | LDELM @str_rat | ||
| + | JMP @pmn_emit | ||
| + | pmn_snake: | ||
| + | LDELM @str_snake | ||
| + | JMP @pmn_emit | ||
| + | pmn_spider: | ||
| + | LDELM @str_spider | ||
| + | pmn_emit: | ||
| + | CALL @print_msg | ||
| + | POP I | ||
| + | POP A | ||
| + | POP ELM | ||
| + | RET | ||
| + | |||
| + | |||
| + | |||
| + | ;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| + | ;; Call with: | ||
| + | ;; ELM is the attacker | ||
| + | ;; FLD is the defender | ||
| + | ;; Note: If player is attacking or defending, | ||
| + | ;; pass @player_obj in ELM or FLD as appropriate. | ||
| + | ;; If the player is not involved, syncing doesn' | ||
| + | ;; | ||
| + | do_combat: | ||
| + | ; sync | ||
| + | CALL @copy_player_to_obj | ||
| + | |||
| + | combat_damage: | ||
| + | ; part 2: damage | ||
| + | LDI @OBJ_DATA1 | ||
| + | LDA [FLD+I] | ||
| + | JZ @combat_msg | ||
| + | DEC AL | ||
| + | STAL [FLD+I] | ||
| + | |||
| + | combat_msg: | ||
| + | CMP ELM, @player_obj | ||
| + | JZ @combat_msg_player | ||
| + | PUSH ELM | ||
| + | LDELM @str_the | ||
| + | CALL @print_msg | ||
| + | POP ELM | ||
| + | |||
| + | CALL @print_mon_name | ||
| + | PUSH ELM | ||
| + | LDELM @str_attacks | ||
| + | CALL @print_msg | ||
| + | POP ELM | ||
| + | JMP @combat_check_dead | ||
| + | |||
| + | combat_msg_player: | ||
| + | PUSH ELM | ||
| + | LDELM @str_you | ||
| + | CALL @print_msg | ||
| + | LDELM @str_attack | ||
| + | CALL @print_msg | ||
| + | POP ELM | ||
| + | |||
| + | combat_check_dead: | ||
| + | LDI @OBJ_DATA1 | ||
| + | LDA [FLD+I] | ||
| + | JNZ @combat_post | ||
| + | CALL @kill_obj | ||
| + | |||
| + | combat_post: | ||
| + | CALL @copy_obj_to_player | ||
| + | |||
| + | combat_done: | ||
| + | RET | ||
| + | |||
| + | |||
| + | kill_obj: | ||
| + | ; Monster dies | ||
| + | ; player will be handled in main loop | ||
| + | PUSH ELM ; save caller' | ||
| + | MOV ELM, FLD ; ELM = victim for everything below | ||
| + | |||
| + | PUSH ELM | ||
| + | LDELM @str_the | ||
| + | CALL @print_msg | ||
| + | POP ELM | ||
| + | CALL @print_mon_name | ||
| + | PUSH ELM | ||
| + | LDELM @str_dies | ||
| + | CALL @print_msg | ||
| + | POP ELM | ||
| + | |||
| + | LDI @OBJ_ID | ||
| + | LDA #0 | ||
| + | STA [ELM+I] | ||
| + | |||
| + | POP ELM ; restore attacker | ||
| + | RET | ||
| + | |||
| + | |||
| + | kill_player: | ||
| + | PUSH ELM | ||
| + | LDELM @str_you_die | ||
| + | CALL @print_msg | ||
| + | POP ELM | ||
| + | |||
| + | ; CLS | ||
| + | LDAH $10 | ||
| + | INT $10 | ||
| + | |||
| + | ; Print "You died." | ||
| + | LDBLX @msg_died | ||
| + | LDAH $66 | ||
| + | INT $05 | ||
| + | |||
| + | POP ELM ; get rid of return address from CALL @draw_map game loop | ||
| + | RET ; exit program. | ||
| + | </ | ||
sd/rogueima_i_mvp-4.1778342817.txt.gz · Last modified: by appledog
