require initDataStructs.fs require pipe.fs require libc.fs require movement.fs : open-input ( addr u -- ) r/o open-file throw to fd-in ; : close-input ( -- ) fd-in close-file throw ; \ create game area : open-world s" world" open-input s" /world [ " wr 0 begin line-buffer max-line fd-in read-line throw while s" [ " wr line-buffer + line-buffer do here i c@ c, 1 wr \ ps i c@ bl <> if dup \ duplicate column i c@ '0' - \ char to int dup E = if \ check if we have something to eat MaxCount @ 1 + MaxCount ! \ increment MaxCount endif swap \ swap row with data i line-buffer - 2 / \ calc column, divide by two because we drop the blanks swap \ swap column and row World ! \ forth then loop 1 + s" ] " wr repeat s" ] def" ln 2drop close-input ; : do-win get-pos-field 10 * swap 10 * swap setPacman lookLeft rot-field-right 62 MS pac-up rot-field-right 62 MS pac-up rot-field-right 62 MS pac-up rot-field-left 62 MS lookUp rot-field-left 62 MS pac-down rot-field-left 62 MS pac-down rot-field-left 62 MS pac-down rot-field-left 62 MS lookRight rot-field-left 62 MS pac-up rot-field-right 62 MS pac-up rot-field-right 62 MS pac-up rot-field-right 62 MS lookDown rot-field-right 62 MS pac-down rot-field-right 62 MS pac-down rot-field-right 62 MS pac-down rot-field-left 62 MS pac-up rot-field-left 62 MS pac-up rot-field-left 62 MS pac-up rot-field-left 62 MS pac-up rot-field-left 62 MS pac-up rot-field-left 62 MS pac-up rot-field-right win ; : check-eat get-pos-field World @ \ s" should eat?" type E = if \ s" Eat" type get-pos-field eat X get-pos-field World ! count @ 1 + dup MaxCount @ = if \ Win nip \ remove key play-win-sound do-win 'q' swap \ set to exit endif count ! endif ; : test-for-exit dup dup 'q' = swap 'Q' = or ; : reset-pos PacStartX PacX ! PacStartY PacY ! lookRight PacX @ MovX ! PacY @ MovY ! get-pos setPacman BotStartX BotX ! BotStartY BotY ! BotX @ MovX ! BotY @ MovY ! get-pos setGhost ; \ wait for keypress : wait-for-key begin 500 MS key? until ; : check-dead \ [ , ) PacX @ BotX @ - -4 5 within PacY @ BotY @ - -4 5 within and if Lives @ 1 - dup 0= if game-over 'q' else lose reset-pos 1000 MS wait-for-key endif Lives ! endif ; \ needs work, can cause pacman to stand still : check-new-dir dup can-go-dir invert \ can't go in the direction the user want's to go if PacDir @ can-go-dir \ can go old direction => keep going if PacWish ! \ save as wish PacDir @ \ set old dir as 'new' else -1 PacWish ! \ reset wish endif else -1 PacWish ! \ reset wish endif ; : bot \ 0 = left, 1 = down, 2 = right , 3 = up BotX @ MovX ! BotY @ MovY ! 0 can-go-dir 1 can-go-dir + 2 can-go-dir + 3 can-go-dir + -1 = if \ we can only go one direction, this means \ we're at the end of a blind alley and have to \ turn around BotDir @ 2 + 4 mod BotDir ! endif BotDir @ dup can-go-dir invert if begin dup can-go-dir invert over BotDir @ 2 + 4 mod = or while drop \ get new dir 4 rand repeat else BotX @ get-sub-field 0= BotY @ get-sub-field 0= and if dup case 0 of random-up-down endof 1 of random-left-right endof 2 of random-up-down endof 3 of random-left-right endof endcase endif endif dup go-dir BotDir ! get-pos setGhost MovX @ BotX ! MovY @ BotY ! ; : play \ init 2 0 PacDir ! \ set old Pacman direction -1 PacWish ! wait-for-key begin delay @ MS PacX @ MovX ! PacY @ MovY ! begin key? while ekey case '-' of delay @ 10 + delay ! endof '+' of delay @ 10 - dup 0 < if 10 + endif delay ! endof '#' of defaultDelay delay ! endof K-LEFT of PacDir ! 0 check-new-dir endof K-RIGHT of PacDir ! 2 check-new-dir endof K-UP of PacDir ! 3 check-new-dir endof K-DOWN of PacDir ! 1 check-new-dir endof 'q' of 'q' endof 'Q' of 'Q' endof endcase repeat PacWish @ -1 <> \ if a wish is available PacWish @ can-go-dir \ we can fulfill the wish and if drop PacWish @ pac-move \ replace dir with wish -1 PacWish ! \ reset wish else pac-move endif \ cr \ quit with q \ print-pac-pos get-pos setPacman check-eat MovX @ PacX ! MovY @ PacY ! bot check-dead test-for-exit until cleanup drop \ remove key which ended loop from stack ; init-rand open-world 3500 MS \ wait for start-sound to be played play bye