-+-+-+-+-+-+-+-+ START OF PART 5 -+-+-+-+-+-+-+-+ X`09brb`0980$`09`09`09; go check for "5", " " X100$: X`09clrl`09r0 X`09rsb X X X`09.entry`09- XMBXREAD,`09`5Em<> X;+ X; This is an AST routine which executes when the mailbox record has been rea Vd. X; The record itself is a status message which is assumed to say that X; unsolicited data is available at the terminal X;- X`09blbc`09mbxiosb, 100$`09`09; on error, dont re-que read X;`09we could have SS$_CANCEL or SS$_ABORT from the $CANCEL in the X;`09exit handler X`09movb`09#1, data_ready`09`09; indicate data is there X`09bsbw`09queue_mbxread`09`09; queue another read request X100$: X`09ret X XQUEUE_MBXREAD: X`09$qio_s`09efn=#2, func=#io$_readvblk, chan=mbxchan, iosb=mbxiosb,- X`09`09astadr=mbxread,- X`09`09p1=mbxbuf, p2=#mbxbuf_siz X`09blbc`09r0, 100$ X`09rsb X100$: X`09bsbw`09error X`09rsb X XTTWRITE:: X;+ X;`09bsbw`09ttwrite X;`09r3 contains length of buffer to write X;`09the buffer is outbuf X;- X`09movl`09r3, outbuf_qio+qio$_p2`09`09; store length of buffer X`09$qiow_g`09outbuf_qio X`09blbc`09r0, 100$ X`09rsb X100$: X`09bsbw`09error X`09rsb X X X`09.entry`09- Xsnake_screen, `5Em X;+ X;`09CALL SNAKE_SCREEN( array, length ) X;`09BYTE ARRAY( LENGTH ) X;`09copies string to update screen into shared memory X;- X`09movl`09@8(ap), r0`09`09; get length X`09movl`09r0, screen_len`09`09; store length X`09movc3`09r0, @4(ap), screen_buf`09; copy text X`09ret X X`09.entry`09- Xsnake_write, `5Em X;+ X;`09CALL SNAKE_WRITE( array, length ) X;`09BYTE ARRAY( LENGTH ) X;`09writes buffer to terminal in noformat mode X;- X`09movl`094(ap), r3`09`09`09; get address X`09movl`09@8(ap), r2`09`09`09; get length X50$: X`09movl`09r2, r0`09`09`09`09; copy length X`09cmpw`09r0, #512`09`09`09; is it too big X`09bleq`0980$`09`09`09`09; br if not X`09movl`09#512, r0 X80$: X`09movl`09r3, output_qio+qio$_p1`09`09; store address of buffer X`09movl`09r0, output_qio+qio$_p2`09`09; store length of buffer X`09addl2`09r0, r3`09`09`09`09; update address X`09subl2`09r0, r2`09`09`09`09; update length X`09$qiow_g`09output_qio X`09blbc`09r0, 100$ X`09tstl`09r2`09`09`09`09; anything else to write ? X`09bgtr`0950$`09`09`09`09; br if yes X`09ret X100$: X`09bsbw`09error X`09ret X X`09.entry`09- Xsnake_dead, `5Em<> X;+ X;`09CALL SNAKE_DEAD( player # ) X;- X`09subl3`09#1, @4(ap), r0`09`09`09; get # of snake who died X`09bbss`09r0, you_just_died, 100$`09`09; set flag saying he died X100$:`09ret X X X XCANCELTYPEAHEAD:: X`09tstw`09ttchan`09`09; check channel is open X`09beql`09100$ X`09$qiow_s`09func=#io$_readvblk!io$m_purge!io$m_timed,- X`09`09chan=ttchan, - X`09`09p1=ttbuf, p2=1, p3=0`09; do read with 0 length buffer (p2) X100$:`09ret`09`09`09`09; return with status in r0 X XERROR: X`09blbs`09r0, 100$ X`09pushl`09r0 X`09calls`09#1, G`5Elib$signal X100$: X`09rsb X X`09.entry`09- Xcontrol_c, `5Em<> X`09movb`09#1, control_c_flag X`09ret X X X`09.page X`09.entry`09- XSNAKE_INIT, `5Em`09`09`09`09; snake game X;+ X;`09I = SNAKE_INIT( player # , game ) X;`09returns I = 1 if you are master snake. X;`09returns your player # as a integer X;`09returns game = 1 if there is a game in progress X;- X X`09calls`09#0, ttinit`09`09`09; open terminal X; X`09$ascefc_s efn=#64, name=snake_desc_2`09; associate event flag cluster X`09bsbw`09error X; X;`09$open`09fab=snake_fab`09`09`09; open section file X;`09bsbw`09error X X`09$deltva_s inadr=map_range`09`09; delete memory were global X`09bsbw`09error`09`09`09`09; memory will be mapped X`09$crmpsc_s inadr=map_range, flags=#sec$m_gbl!sec$m_wrt!sec$m_pagfil,- X`09`09gsdnam=snake_map_name, - ; chan=snake_fab+fab$l_stv,`20 X`09`09pagcnt=#4 X`09bsbw`09error X`09cmpl`09r0, #ss$_created`09`09; are we first to map section X`09bneq`0950$`09`09`09`09; no X`09movab`09share_data+4, r3 X`09movc5`09#0, (r3), #0, #512-4, (r3)`09; clear everything except count X`09$clref_s efn=#flag$v_game+64`09`09; say not game X`09movl`09#39814571, seed`09`09`09; init random n.g. seed X`09movl`09#snake, r0`09`09`09; 8 snakes X20$: X`09movl`09r0, start_position-4`5Br0`5D`09; init start position X`09sobgtr`09r0, 20$ X50$: X`09blbc`09abort, 60$`09`09`09; if not abort --> 60$ X`09callg`09text_abort, snake_write X`09$exit_s #1 X60$: X;`09$qio_g`09read_qio`09 `09; start read of another character X;`09the above line shifted into SNAKE_START X X;`09bsbw`09queue_mbxread`09`09`09; start terminal read X; X`09bbss`09#0, master_flag, 100$`09`09; see if a master snake exists X`09`09`09; this should be interlocked on a multi-processor X;+ X; We will have to be the master snake X;- X`09movb`09#1, master`09`09`09; indicate we are master snake X`09$setef_s efn=#7`09`09`09`09; set for first call X100$: X; X`09clrl`09r1`09`09`09`09; start at player 0 (bit0=1) X150$: X`09bbcs`09r1, players, 200$`09`09; see if this snake is free X`09incl`09r1`09`09`09`09; go to next snake X`09cmpl`09r1, #snake`09`09`09; have we checked all snakes? X`09blss`09150$`09`09`09`09; no --> 150$ X`09mnegl`09#1, r1`09`09`09`09; player = -1 means none X200$: X`09movl`09r1, player`09`09`09; store my snake number (0-7) X`09movl`09player, @4(ap)`09`09`09; and return it X500$: X`09movzbl`09game_going, @8(ap)`09`09; return game going flag X X`09movl`09r1, r3 X`09blss`09600$`09`09`09`09; no snakes available X`09$getjpi_s itmlst=username_jpi`09`09; get our username X`09mull2`09#name_size, r3`09`09`09; get offset to start of name X`09movc5`09username_siz, username_buf, #`5Ea/ /, #name_size, name(r3) X`09`09`09`09`09`09; copy username X600$: X`09$dclexh_s desblk=exit_block`09`09; declare exit handler X`09bsbw`09error X;+ X;`09init translation table for converting all ascii chars for your X;`09snake to a diamond X;- X`09movab`09trans_table, r3 X`09clrl`09r4 X700$: X`09movb`09r4, (r3)+`09`09`09; store byte X`09aoblss`09#256, r4, 700$ X`09movl`09player, r0`09`09`09; get our player # X`09blss`09800$`09`09`09`09; br if no players available X`09movb`09#`5EA/`60/, trans_table+`5EA/1/+`5EX80(r0)`09; convert us to diamo Vnd X`09movab`09trans_table+128, r3 X`09movb`09#`5EA/1/, `5EA/a/(r3) X`09movb`09#`5EA/2/, `5EA/b/(r3) X`09movb`09#`5EA/3/, `5EA/c/(r3) X`09movb`09#`5EA/4/, `5EA/d/(r3) X`09movb`09#`5EA/5/, `5EA/e/(r3) X`09movb`09#`5EA/6/, `5EA/f/(r3) X`09movb`09#`5EA/7/, `5EA/g/(r3) X`09movb`09#`5EA/8/, `5EA/h/(r3) X`09movb`09#`5EA/ /, trans_table+`5EA/a/+`5EX80(r0)`09; convert us to space X800$: X X`09movzbl`09master, r0`09`09`09; return master snake status X`09ret X Xmaster_wait: X;+ X; master snake has to wait some time for other snakes to start playing X; called from SNAKE_START X;- X`09incl`09game_count`09`09`09; say another game being played X220$:`09clrb`09player_bits`09`09`09; no other players X`09bbss`09player, player_bits, 400$`09; say I am playing X400$: X`09$clref_s efn=#flag$v_synch+64 X X.if ne $$MQIX 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.endc X X.if ne $$SOCCER X`09movab`09move, r3 X`09clrq`09(r3)+`09`09`09`09; no move to start with X`09clrq`09(r3)+ X.endc 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`09$cancel_s chan=ttchan`09`09`09; cancel the outstanding read 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;;`09calls`09#0, canceltypeahead X`09$qio_g`09read_qio`09 `09; start read of another character X X.if ne $$MQIX 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 X910$: X`09movl`09(r0)+, (r2)+ X`09sobgtr`09r1, 910$ X.endc X X;`09init starting directions X`09movaw`09move, r2`09`09`09; address of where to put them X`09movl`09#snake, r1`09`09`09; number of snakes X900$: X.if ne $$MQIX X`09movb`09#`5EA/9/, (r2)+`09`09`09; 9 = invalid move X.endc X X.if ne $$SOCCER X`09movw`09#5, (r2)+`09`09`09; 5 = stop X.endc X 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`09movl`09player, r1`09`09`09; get our player number X X.if ne $$SOCCER X`09tstw`09r0`09`09`09`09; anything typed ? X`09beql`0910$`09`09`09`09; br if no X`09movw`09r0, move`5Br1`5D`09`09`09; store our move X.endc X X.if ne $$MQIX X`09tstb`09r0`09`09`09`09; anything typed ? X`09beql`0910$ X`09blss`095$ X`09movb`09r0, move`5Br1`5D`09`09`09; store our move X`09brb`0910$ X5$: X`09bisb2`09r0, move`5Br1`5D`09`09`09; r0 = `5EX80 (set parity bit) X.endc X X10$: 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, L`5Eadd_head ; call Pascal routine X`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 X.if ne $$SOCCER X`09movc3`09screen_len, screen_buf, outbuf`09; copy update string X.endc X X.if ne $$MQIX X;`09replace your snake head with a diamond symbol X`09movl`09screen_len, r0`09`09; get length of output string X`09movtc`09r0, screen_buf, #`5EA/ /, trans_table, r0, outbuf X.endc X X;`09movl`09player, r2`09`09; get my snake number +-+-+-+-+-+-+-+- END OF PART 5 +-+-+-+-+-+-+-+-