001: ; brilliant.g
002: 
003: ; a variant of smart.g
004: ; avoid entering dead-ends unless lambda-man is there
005: 
006: %lastx :: [1]
007: %lasty :: [2]
008: %clkl :: [3]
009: %clkh :: [4]
010: %curmode :: [5]        ; 0 = chase, 1 = scatter
011: %scatterx :: [6]
012: %scattery :: [7]
013: %principal :: [8]
014: %secondary :: [9]
015: ; declarations for follow
016: %good_dir_val     :: [248]
017: %good_dir_num     :: [249]
018: %current_x   :: [250]
019: %current_y   :: [251]
020: %current_dir :: [252]
021: 
022: ; clock
023:   add %clkl, 8               ; clock high period 256/8 = 32
024:   jgt clock_done, %clkl, 0
025:   inc %clkh
026: clock_done:
027: 
028: ; detect sudden jumps in position and reset the clock
029:   int 3
030:   int 5
031:   sub a, %lastx
032:   sub b, %lasty
033:   add a, b
034:   add a, 1
035:   jlt detect_done, a, 3
036:   mov %clkl, 0
037:   mov %clkh, 0
038: detect_done:
039:   int 3
040:   int 5
041:   mov %lastx, a
042:   mov %lasty, b
043: 
044: ; decide between chase and scatter
045: 
046: ; if panic mode, scatter
047: 
048:   int 3
049:   int 6
050:   jeq scatter, a, 1    ; panic mode -> scatter
051:   jeq chase, a, 2      ; invisible mode -> chase
052:                        ; normal mode -> scatter/chase according to clock
053: 
054: ; if clock-high = 0 mod 4, scatter
055:   mov c, %clkh
056:   and c, 3
057:   jgt chase, c, 0
058: 
059: scatter:
060:   jeq scatter_continue, %curmode, 1
061:   mov %curmode, 1
062:   mov c, %clkh
063:   div c, 8
064:   int 3
065:   add a, c
066:   mov %scatterx, a
067:   div a, 2
068:   mov %scattery, a
069:   and %scatterx, 1
070:   and %scattery, 1
071:   mul %scatterx, 30
072:   mul %scattery, 30
073:   sub %scatterx, 15
074:   sub %scattery, 15
075:   int 3
076:   int 1
077:   add %scatterx, a
078:   add %scattery, b
079:   jlt clipxdone, %scatterx, 128
080:   mov %scatterx, 0
081: clipxdone:
082:   jlt clipydone, %scattery, 128
083:   mov %scattery, 0
084: clipydone:
085: scatter_continue:
086:   mov a, %scatterx
087:   mov b, %scattery
088:   jmp go_to
089: 
090: chase:
091:   mov %curmode, 0
092:   int 1     ; get lman's coordinates in A and B
093: 
094: go_to:
095:   mov c, a  ; c = lman.x
096:   mov d, b  ; d = lman.y
097:   int 3     ; get this ghost's index
098:   int 5
099:   mov e, a  ; e = my.x
100:   mov f, b  ; f = my.y
101: 
102: ; compute direction
103: 
104:   mov a, 1     ; alpha
105:   mov b, 1     ; phi
106:   mov g, c
107:   sub g, e     ; absx = dx  = lman.x - my.x
108:   mov h, f
109:   sub h, d     ; absy = -dy = my.y - lman.y
110: 
111:   jgt l1, c, e     ; if lman.x =< my.x then
112:     add a, 6
113:     mov g, e
114:     sub g, c   ; absx = -dx
115:     xor b, 254 ; phi := -phi
116: l1:
117:   jlt l2, d, f     ; if lman.y >= my.y then
118:     xor a, 2
119:     mov h, d
120:     sub h, f   ; absy = dy
121:     xor b, 254 ; phi := -phi
122: 
123: 
124: l2:
125: ; from now on, c and d are the main and secondary direction
126:   mov c, a
127:   mov d, a
128: 
129:   jlt l3, g, h    ; if absx >= absy then
130:     xor b, 254    ; phi := -phi
131: l3:
132:     sub c, b      ; add phi for main direction
133:     add d, b      ; subtract phi for secondary direction
134: 
135: l4:
136:   div c, 2        ; main direction of lambda-man
137:   div d, 2        ; secondary direction
138:   and c, 3
139:   and d, 3
140: test:
141:   int 3
142:   int 5
143:   mov %principal, c
144:   mov %secondary, d
145: 
146:   mov [254], c
147:   mov [255], ret1
148:   mov PC, next    ; get coordinates of square in direction c
149: ret1:
150:   int 7           ; get square
151:   jeq secondary, a, 0    ; go in main direction if not wall
152: 
153:   int 3
154:   int 6           ; get ghost current direction
155:   add b, 2        ; reverse the direction
156:   and b, 3        ; reverse the direction, cont.
157:   and %principal, 3        ; clip the principal direction
158:   jeq secondary, b, %principal   ; check if principal direction is forbidden
159:   int 3
160:   int 5
161:   mov %current_dir, %principal
162:   mov [253], testing_if_good_path
163:   mov PC, follow
164: testing_if_good_path:
165:   MOV H, A
166:   INT 3
167:   INT 5
168:   ;; MOV F, A
169:   ;; MOV G, B
170:   ;; MOV D, %principal
171:   ;; MOV E, %secondary
172:   ;; MOV C, %curmode
173:   ;;  int
174:   jmp go          ; principal direction is valid
175: 
176: secondary:
177:   mov %principal, %secondary        ; go in secondary direction
178: 
179: go:
180:   and %principal, 3        ; reduce modulo 4
181:   mov a, %principal
182:   int 0           ; direction is in a
183:   hlt
184: 
185: 
186: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
187: ; follow a <- X, b <- Y, %current_dir<- DIR, [253] <- RETURN
188: ; return 0 in a if it is a good choice, and something else otherwise
189: follow:
190:    ;; MOV C, %current_dir          ; debug
191:    ;; MOV H, 42                    ; debug
192:    ;; int 8                        ; debug
193:    MOV [254], %current_dir
194:    MOV [255], lfollow1
195:    MOV PC, next
196: lfollow1:
197:   ; we are in the first tile of the path
198:   ;; MOV H, 43
199:   ;; INT 8
200:   MOV %good_dir_num, 0
201:   MOV %current_x, a
202:   MOV %current_y, b
203: 
204: ; check for the presence of lambda-man
205:   int 1
206:   jeq checky, a, %current_x
207:   jmp checkdone
208: checky:
209:   jeq return_ok_lambda, b, %current_y
210: checkdone:
211:   mov a, %current_x
212:   mov b, %current_y
213:   MOV [254], %current_dir      ; prepare the call to next for current dir
214:   MOV [255], lwalling0         ; prepare the call...
215:   MOV PC, next
216: lwalling0:
217:   ;; MOV H, 44
218:   ;; INT 8
219:   INT 7
220:   JEQ lwalling2, A, 0
221:   MOV %good_dir_val, %current_dir
222:   INC %good_dir_num
223: lwalling1:
224:   INC %current_dir
225:   AND %current_dir, 3
226:   MOV a, %current_x
227:   MOV b, %current_y
228:   ;; mov c, %current_dir           ; debug
229:   ;; mov h, 45                     ; debug
230:   ;; INT 8                         ; debug
231:   MOV [254], %current_dir      ; prepare the call to next for current dir
232:   MOV [255], lwalling2         ; prepare the call...
233:   MOV PC, next
234: lwalling2:
235:   ;; MOV H, 44
236:   ;; INT 8
237:   INT 7
238:   JEQ lwalling3, A, 0
239:   MOV %good_dir_val, %current_dir
240:   INC %good_dir_num
241: lwalling3:
242:   ADD %current_dir, 2
243:   AND %current_dir, 3
244:   MOV a, %current_x
245:   MOV b, %current_y
246:   MOV [254], %current_dir      ; prepare the call to next for current dir
247:   MOV [255], lwalling4         ; prepare the call...
248:   MOV PC, next
249: lwalling4:
250:   ;; MOV H, 44
251:   ;; INT 8
252:   INT 7
253:   JEQ lwalling5, A, 0
254:   MOV %good_dir_val, %current_dir
255:   INC %good_dir_num
256: lwalling5:
257:   JEQ not_ok, %good_dir_num, 0
258:   JEQ continue, %good_dir_num, 1
259: ;return_ok_lambda:
260: return_ok:
261:   MOV A,0
262:   MOV PC, [253]
263: not_ok:
264:   MOV A,1
265:   MOV PC, [253]
266: continue:
267:   MOV %current_dir, %good_dir_val
268:   MOV A, %current_x
269:   MOV B, %current_y
270:   MOV PC, follow
271: 
272: return_ok_lambda:     ; debug
273:   int 8               ; debug
274:   jmp return_ok       ; debug
275: 
276: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
277: ; next a <- X, b <- Y, [254] <- DIR, [255] <- RETURN
278: ;;  this function has zero bug.
279: next:
280:         MUL [254], 2
281:         ADD [254], 3
282:         MOV H, PC
283:         ADD H, [254]
284:         MOV PC, H
285:         SUB B, 1                ; code for 0
286:         JMP next_end
287:         ADD A, 1                ; code for 1
288:         JMP next_end
289:         ADD B, 1                ; code for 2
290:         JMP next_end
291:         SUB A, 1                ; code for 3
292: next_end:
293:         MOV PC, [255]
294: