-+-+-+-+-+-+-+-+ START OF PART 5 -+-+-+-+-+-+-+-+ X`09$clref_s efn=#flag$v_synch+64 X;+ X;`09randomise starting positions X;- X`09moval`09start_position, r4`09`09; starting position numbers X`09movl`09#1, r2`09`09`09`09; snake index (start at 1) X500$: X`09pushal`09seed`09`09`09`09; random number seed X`09calls`09#1, G`5Emth$random`09`09; random real in r0 X`09addl3`09#1, r2, r3`09`09`09; snake + 1 X`09cvtlf`09r3, r3`09`09`09`09; as real X`09mulf2`09r3, r0`09`09`09`09; get snake to change pos with X`09cvtfl`09r0, r0 X`09movl`09(r4)`5Br0`5D, r1`09`09`09; swap these positions X`09movl`09(r4)`5Br2`5D, (r4)`5Br0`5D X`09movl`09r1, (r4)`5Br2`5D X`09aobleq`09#7, r2, 500$ X; X;`09moval`09start_position, r4 X`09movab`09move, r3 X`09movl`09#snake, r2`09`09`09; number of snakes X600$: X`09movl`09(r4)+, r0`09`09`09; get start position (1-8) X`09movb`09start_direction-1`5Br0`5D, (r3)+`09; copy start direction X`09sobgtr`09r2, 600$ X; X`09$setimr_s efn=#flag$v_game+64,-`20 X`09`09`09daytim=second_1`09`09; wait a time for other snakes X`09$waitfr_s efn=#flag$v_game+64`09`09; say that a game is going X`09movb`09#1, game_going`09`09`09; say game going X`09$clref_s efn=#flag$v_endofgame+64`09; say not end of game X`09$setef_s efn=#7`09`09`09`09; sets event flag for first X`09`09`09`09`09`09; call to snake_wait X`09$setimr_s efn=#flag$v_synch+64,-`09`09 X`09`09`09 daytim=start_wait X`09$waitfr_s efn=#flag$v_synch+64 X`09; this allows other snakes to set bit saying they are playing X X`09rsb X X`09.entry`09- XSNAKE_START, `5Em X;+ X;`09CALL SNAKE_START( PLAYERS , START_POSITION ) X;`09INTEGER PLAYERS, START_POSITION(8) X;`09waits 5? seconds for other players to run game X;`09The master snake is assumed to have waited some additional time X;`09Returns PLAYERS, bit I <> 0 if that player is active X;`09START_POSITION(I) is the starting location of snake I, (1-8) X;- X`09blbc`09master, 500$`09`09`09; are we master snake ? X`09bsbw`09master_wait X`09brb`09800$ X200$: X`09$exit_s #1`09`09`09`09; game aborted so stop X500$: X`09$waitfr_s efn=#flag$v_game+64`09`09; wait until a game starts X`09blbs`09abort, 200$`09`09`09; if game stopped --> 200$ X`09bbss`09player, player_bits, 600$`09; say I am playing X600$:`09$waitfr_s efn=#flag$v_synch+64`09`09; synchronise X`09blbs`09abort, 200$`09`09`09; if game stopped --> 200$ X800$: X`09movzbl`09player_bits, r4`09`09`09; get player bits X`09ashl`09#flag$v_done, r4, other_players ; used by master snake X`09movl`09r4, @4(ap)`09`09`09; store player bits X`09clrl`09chars_left`09`09`09; cancel type ahead X`09clrb`09data_ready`09`09`09; make us do a read X`09$qiow_g read_qio`09`09`09; clear out type-ahead X;`09return starting positions X`09moval`09start_position, r0`09`09; address of new positions X`09movl`098(ap), r2`09`09`09; address of where to put them X`09movl`09#snake, r1`09`09`09; number of snakes X900$: X`09movl`09(r0)+, (r2)+ X`09sobgtr`09r1, 900$ X X`09mnegl`09#1, last_move_count`09`09; invalidate last counter X X`09ret X X XSNAKE_WAIT:: X;+ X;`09BSBW SNAKE_WAIT X; `09wait until we are told to read players command(s) X;- X`09blbs`09master, 200$`09`09`09; are we master snake ? X`09$waitfr_s efn=#flag$v_read+64`09`09; if not then wait for flag X`09rsb X200$:`09; master snake waits and then sets flag for all players X`09$cantim_s reqidt=#check_timer`09`09; cancel checking timer X`09$waitfr_s efn=#7`09`09`09; wait for previous timer X`09$setimr_s efn=#8, daytim=check_wait, - X`09`09astadr=check_ast, reqidt=#check_timer ; set off checking timer X`09$setimr_s efn=#7, daytim=update_wait X`09$clref_s efn=#flag$v_update+64`09`09; clear next flag to wait on X`09movl`09#flag$v_done+64, r2`09`09; clear each players done flag X`09$clref_s efn=r2`09`09`09`09; player 0 X`09incl`09r2 X`09$clref_s efn=r2 X`09incl`09r2 X`09$clref_s efn=r2 X`09incl`09r2 X`09$clref_s efn=r2 X`09incl`09r2 X`09$clref_s efn=r2 X`09incl`09r2 X`09$clref_s efn=r2 X`09incl`09r2 X`09$clref_s efn=r2 X`09incl`09r2 X`09$clref_s efn=r2`09`09`09`09; player 7 X; X`09$clref_s efn=#flag$v_synch+64 X`09$setef_s efn=#flag$v_read+64`09`09; tell everybody to do read X`09rsb X X XSNAKE_READ:: X;+ X;`09BSBW SNAKE_READ X;`09read all users moves and store them into the byte array MOVES(*) X;- X`09bsbw`09ttread`09`09`09`09; read users commands, if any X`09tstb`09r0`09`09`09`09; anything read ? X`09blss`09800$`09`09`09`09; no X500$: X`09movl`09player, r1`09`09`09; get our player number X`09movb`09r0, move(r1)`09`09`09; store our move X`09bneq`09800$`09`09`09`09; if not quit --> 800$ X`09clrl`09score`5Br1`5D`09`09`09; clear score X`09clrl`09n_games`5Br1`5D X`09clrl`09wins`5Br1`5D X`09$exit_s #1`09`09`09`09; and exit program X800$: X`09addl3`09#flag$v_done+64, player, r1 X`09$setef_s efn=r1`09`09`09`09; say that read is complete X900$: X`09blbc`09master, 1000$ X`09$wfland_s efn=#64, mask=other_players`09; wait for all players to read X`09incl`09move_count`09`09`09; onto next move X`09$clref_s efn=#flag$v_read+64`09`09; clear next flag to wait on X`09$setef_s efn=#flag$v_update+64`09`09; tell everybody to update X`09brb`091050$ X1000$: X`09$waitfr_s efn=#flag$v_update+64`09`09; wait for all reads to complete X`09blbs`09master_flag, 1050$`09`09; check for master snake OK X`09movl`09player, r1`09`09`09; get our player number X`09clrb`09move(r1)`09`09`09; store our move ( quit ) X1050$: X`09rsb X X X`09.entry`09- XSNAKE_PLAY, `5Em X;+ X;`09called once at the start of the game. X;`09I then call the Pascal routine ADD_HEAD to perform the moves. X;- X`09blbs`09master, 1000$`09`09; master snake does all the work X100$: X`09bsbw`09snake_wait X`09bsbw`09snake_read X`09$waitfr_s efn=#flag$v_synch+64`09; wait until screen update there X`09bsbw`09snake_update`09`09; update screen X`09brb`09100$ X X900$: X`09clrb`09game_going`09`09; tell other snakes games finished X`09$setef_s efn=#flag$v_synch+64`09; wake other snakes up X`09bsbb`09snake_update`09`09; write out last move X`09ret X X1000$:`09; master snake moves every snake X`09bsbw`09snake_wait X`09bsbw`09snake_read X`09callg`09add_head_par, G`5Eadd_head`09; call Pascal routine X`09`09`09`09`09`09; returns 1 if game still going X`09blbc`09r0, 900$`09`09; game has ended --> 900$ X`09$setef_s efn=#flag$v_synch+64`09; wake other snakes up X`09bsbb`09snake_update`09`09; update our screen X`09brb`091000$ X X X`09.enable local_block X500$: X`09$exit_s #1`09`09`09; game aborted, so exit image X Xsnake_update:: X`09blbs`09abort, 500$ X`09blbs`09dead, 80$`09`09; if we are dead, then no head X;`09replace your snake head with a diamond symbol X`09movc3`09screen_len, screen_buf, outbuf`09; copy update string X`09movl`09player, r2`09`09; get my snake number X`09addw2`09#`5EA/1/+`5EX80, r2`09`09; get number with parity bit set X`09locc`09r2, screen_len, outbuf X`09beql`0950$`09`09`09; could not find it !!! X`09movb`09#`5EA/`60/, (r1)`09`09; change to diamond X50$: X`09callg`09update_par, snake_write X`09blbc`09game_going, 100$`09; bit clear if game has finished X`09bbsc`09player, you_just_died, 60$ ; see if we just died X`09rsb X60$:`09movb`09#1, dead`09`09; say we are dead X`09callg`09text_wait, snake_write`09; tell them to wait for next game_exit, X`09rsb X80$:`09; dont copy buffer if no head to update because we are dead X`09callg`09update_par2, snake_write X`09blbc`09game_going, 100$ X`09rsb X100$: X`09$setimr_s efn=#6, daytim=second_1`09; so we can see last move X`09$waitfr_s efn=#6 X`09ret`09`09`09`09; return from SNAKE_PLAY if end game X`09.disable local_block X X X`09.entry`09- XCHECK_AST, `5Em X;+ X;`09called when check_timer expires (2 seconds) X;`09we should only get here if one of the other snakes has aborted X;`09or `5ES ed . Force the snake out of the game. X;- X`09$readef_s efn=#64, state=cluster_2`09; get done flags X`09extzv`09#flag$v_done, #snake, cluster_2, r2 ; get done flags X;`09movb`09other_players+1, r3`09`09; get other players X`09bicw3`09r2, other_players+1, r3`09`09; find players who have not X`09`09`09`09`09`09; responded X`09bicw2`09r3, other_players+1`09`09; and say they are dead X`09clrl`09r2`09`09`09`09; snake 0 X100$:`09bbc`09r2, r3, 200$ X`09clrb`09move(r2)`09`09`09; say snake has quitted X`09addl3`09#flag$v_done+64, r2, r0`09`09; get event flag X`09$setef_s efn=r0`09`09`09`09; set event flag so I will X`09`09`09`09`09`09; wake up on return from here X200$:`09aoblss`09#snake, r2, 100$`09`09; for all 8 snakes X X`09ret X X X`09.entry`09- XSNAKE_GAME_END, `5Em<> X;+ X;`09synchronizes the end of the game X;- X`09clrb`09dead`09`09`09; we are not dead X`09blbc`09master, 500$`09`09; if not master snake --> 500$ X`09$clref_s efn=#flag$v_game+64`09; say game not in progress X`09clrb`09game_going`09`09; and again X`09$setimr_s efn=#flag$v_endofgame+64, daytim=second_2 X`09clrw`09you_just_died`09`09; reset died flags X500$: X`09$waitfr_s efn=#flag$v_endofgame+64 ; wait for end of game X`09blbs`09abort, 800$`09`09; if we should abort --> 800$ X`09ret X800$:`09; we must abort. Probably because master snake stopped X`09$exit_s #1 X X X`09.entry`09- XSNAKE_EXIT, `5Em X;+ X;`09called as an exit handler X;- X`09$cancel_s chan=mbxchan`09`09; cancel mailbox read X X`09movl`09player, r3`09`09; get my snake number X`09blss`0980$`09`09`09; we never were playing X`09clrb`09move(r3)`09`09; make next move a quit X`09addl3`09#flag$v_done, r3, r2`09; get done bit X`09bbcc`09r2, other_players, 50$`09; stop master snake from waiting for me X50$:`09addl2`09#64, r2`09`09`09; make into event flag X`09$setef_s efn=r2`09`09`09; say input done X`09bbcc`09r3, players, 60$`09; say this snake available X60$: X`09clrl`09score`5Br3`5D`09`09; zero score X`09clrl`09n_games`5Br3`5D`09`09; zero # of games played X80$: X`09blbc`09master, 100$`09`09; are we master snake ? X`09movb`09#1, abort`09`09; tell all other snakes to abort X`09clrb`09master_flag`09`09; say no master snake X`09$setef_s efn=#flag$v_read+64`09; wake everybody up X`09$setef_s efn=#flag$v_update+64 X`09$setef_s efn=#flag$v_endofgame+64 X`09$setef_s efn=#flag$v_synch+64 X`09$setef_s efn=#flag$v_game+64`09; for people waiting for a game X100$: X;`09clear screen and put out of graphics mode X`09callg`09text_end_game, snake_write X`09blbc`09abort, 200$`09`09; game is not being aborted --> 200$ X`09callg`09text_abort, snake_write X200$: X`09$deltva_s inadr=ret_range`09; delete global section X`09$dassgn_s chan=snake_fab+fab$l_stv ; deassign channel X X`09ret X X`09 X`09.entry`09- XNAME_SET, `5Em X;+ X;`09CALL NAME_SET( name ) X;`09set this players name X;- X`09mull3`09#name_size, player, r3`09; get our player number (0-7) X`09addl2`09#13, r3`09`09`09; skip username X`09movc3`09#name_size-13, @4(ap), name(r3) ; store name in shared memory X`09ret X X`09.entry`09- XNAME_GET, `5Em X;+ X;`09CALL NAME_GET( name , player # ) X;`09returns the name of specified player (1-8) X;- X`09subl3`09#1, @8(ap), r1`09`09; get player number (0-7) X`09mull2`09#name_size, r1`09`09; offset to this players name X`09movc3`09#name_size, name(r1), @4(ap) ; return players name X`09ret X X`09.entry`09- XSCORE_SET, `5Em<> X;+ X;`09CALL SCORE_SET( player #, score , # games , # wins ) X;- Xplayer_arg = 4 Xscore_arg = 8 Xgames_arg = 12 Xwins_arg = 16 X`09subl3`09#1, @player_arg(ap), r1`09`09; get our player # (0-snake) X`09movl`09@score_arg(ap), score`5Br1`5D`09; store score X`09movl`09@games_arg(ap), n_games`5Br1`5D X`09movl`09@wins_arg(ap), wins`5Br1`5D X`09ret X X`09.entry`09- XSCORE_GET, `5Em<> X;+ X;`09CALL SCORE_GET( player , score , # games , # wins ) X;- X;player_arg = 4 X;score_arg = 8 X;games_arg = 12 X;wins_arg = 16 X`09subl3`09#1, @player_arg(ap), r1`09`09; get player # (0-snake) X`09movl`09score`5Br1`5D, @score_arg(ap)`09; return score X`09movl`09n_games`5Br1`5D, @games_arg(ap)`09; return # of games played X`09movl`09wins`5Br1`5D, @wins_arg(ap)`09`09; return # of wins X`09ret X X`09.entry`09- Xsnake_game_count, `5Em<> X;+ X;`09CALL SNAKE_GAME_COUNT( # games ) X;`09returns # of games played (total) X;- X`09movl`09game_count, @4(ap) X`09ret X X`09.end $ CALL UNPACK TANKM.MAR;1 1057110803 $ v=f$verify(v) $ EXIT