;Ben Pew - 0860635 ;Compsci 210 ;Lab - Thursday 7:00 - 8:20 (define pbs1 (list (list '- '- '- '- '- '-) (list '- '- '- '- '- '-) (list '- '- '- '- '- '-) (list '- '- '- '- '- '-) (list '- '- '- '- '- '-) (list '- '- '- '- '- '-))) ;(build-vector 4 (lambda (x) x)) (define MAX-BOARD-SIZE 5) (define connectx 5) (define me-s 'X) (define op-s 'O) (define blank '-) ;getmove: -> list of lists ;getmove gets the current board and returns it. (define (getmove) (read)) ;a matrix is a vector of vectors ;lol-vov: list of lists -> vector of vectors ;lol-vov turns a list of lists into a vector of vectors. (define (lol-vov a-lol) (local [(define list-counter (+ 2 (length a-lol)))] (begin (set! MAX-BOARD-SIZE (- list-counter 2)) (build-vector list-counter (lambda (x) (if (or (= x 0) (= (add1 x) list-counter)) (make-vector list-counter 'T) (build-vector list-counter (lambda (y) (if (or (= y 0) (= (add1 y) list-counter)) 'T (list-ref (sub1 x) (sub1 y) a-lol)))))))))) ;list-ref: num num list -> entry ;list-ref returns the [ith, jth] value of a list of lists where i is the value in the outer list and j is the one in the inner list (define (list-ref i j a-list) (cond [(= 0 i) (if (= 0 j) (first (first a-list)) (list-ref 0 (sub1 j) (list (rest (first a-list)))))] [else (list-ref (sub1 i) j (rest a-list))])) (define pbs-v1 (lol-vov pbs1)) ;pbs-v1 ;m-r: position matrix -> entry ;m-r returns the ith, jth entry in a matrix. (define (m-r p m) (vector-ref (vector-ref m (first p)) (second p))) ;(m-r (list 2 1) pbs-v1) = 'X ;(m-r (list 0 4) pbs-v1) = 'T ;(m-r (list 3 1) pbs-v1) = '- ;(m-r (list 3 2) pbs-v1) = 'O ;a position is a list containing two values ;these next couple of programs will be used by a master/control program which will use all these in the order listed ;or close to that order. ;lets assign danger levels of nme programs first ;defense ;4 unbounded is a lose, but it is easy to detect. .9 ;4 bounded is a lose if not blocked or cannot be immediatly beaten - danger level of .9 ;3 bounded - .25 ;2 bounded - .01 ;3 unbounded is a lose if not blocked, or if I have winning move in two turns. (a must be win) .8 ;2 unbounded - .25 ;1 unbounded - .02 ;3 bounded - .01 (blockable, but if no good offensive move, these are not good to let sit around) (yet at the same time, this should not ovveride any ;other choice) ;offense: ;create 5 bounded or unbounded - 1 ;create 4 unbounded - .85 ;create 1 3 unbounded - .55 ;create 1 2 unbounded - .3 ;create 1 4 bounded - .65 ;create 1 3 bounded - .2 ;create 1 2 bounded - .03 ;anything below this is not kept track of (value of 0) ;combinations of these are added together in the total value (making them very very valuable) ;when 5, 4, 3, 2, or 1 is said it means connectx-0, 1, 2, 3, or 4 respectively. ;a space contains ;a position and ;the total move value (num) and ;the highest single value for the offense (num) and, ;the highest single value for a defensive move.(num) (define-struct space (position t-v o-v d-v)) ;find-spaces: matrix num num list of positions -> list of positions ;find-spaces returns a list of all possible places to put a move. (define (find-spaces board i j accum) (cond [(= i MAX-BOARD-SIZE) (if (= (sub1 j) MAX-BOARD-SIZE) accum (if (symbol=? blank (m-r (list i j) board)) (find-spaces board i (add1 j) (cons (list i j) accum)) (find-spaces board i (add1 j) accum)))] [(= j MAX-BOARD-SIZE) (if (symbol=? blank (m-r (list i j) board)) (find-spaces board (add1 i) 1 (cons (list i j) accum)) (find-spaces board (add1 i) 1 accum))] [else (if (symbol=? blank (m-r (list i j) board)) (find-spaces board i (add1 j) (cons (list i j) accum)) (find-spaces board i (add1 j) accum))])) ;f-s: board -> list of positions ;f-s is a wrapper function for find-spaces, it finds all possible places to put a move. (define (f-s board) (find-spaces board 1 1 empty)) ;(f-s pbs-v1) ;compute-value: position board -> space ;compute value takes in a position and returns its value, in the form of a structure called a space. (define (compute-value a-pos board) (local [(define right (streak-handeler 1 0 a-pos board)) (define up (streak-handeler 0 1 a-pos board)) (define diag1 (streak-handeler 1 1 a-pos board)) (define diag2 (streak-handeler -1 1 a-pos board)) (define streak-list (list right up diag1 diag2)) (define offense (high-streak streak-list space-o-v -1)) (define defense (high-streak streak-list space-d-v -1)) (define total-value (value-summation streak-list 0))] (make-space a-pos total-value offense defense))) ;value-summation: list of spaces num -> num ;value-summation returns the total value of a list of spaces (define (value-summation los accum) (cond [(empty? los) accum] [else (value-summation (rest los) (+ accum (space-o-v (first los)) (space-d-v (first los))))])) ;high-streak: list of spaces func num -> num ;determines the highest possible value of the func on the first on the list. (define (high-streak los func high-val) (cond [(empty? los) high-val] [else (if (> (func (first los)) high-val) (high-streak (rest los) func (func (first los))) (high-streak (rest los) func high-val))])) ;a helper is a structure made to do simply what it says, help ;it is used when determining the value of streaks. ;it contains a lenght and ;a bool, b which is for whether or not it is blocked. (True for blocked, false for not blocked) (define-struct helper (l b)) ;streak-handeler: num num pos board -> space ;returns a space based on a streak. (define (streak-handeler d1 d2 a-pos board) (local [(define right-o (streaker d1 d2 me-s a-pos board)) (define right-d (streaker d1 d2 op-s a-pos board)) (define left-o (streaker (- 0 d1) (- 0 d2) me-s a-pos board)) (define left-d (streaker (- 0 d1) (- 0 d2) op-s a-pos board)) (define offense (cond [(and (helper-b right-o) (helper-b left-o)) (if (>= (+ (helper-l right-o) (helper-l left-o)) (sub1 connectx)) 1 0)] [(or (helper-b right-o) (helper-b left-o)) (cond [(>= (+ (helper-l right-o) (helper-l left-o)) (sub1 connectx)) 1] [(= (+ (helper-l right-o) (helper-l left-o)) (- connectx 2)) .65] [(= (+ (helper-l right-o) (helper-l left-o)) (- connectx 3)) .2] [(= (+ (helper-l right-o) (helper-l left-o)) (- connectx 4)) .03] [else 0])] [else (cond [(>= (+ (helper-l right-o) (helper-l left-o)) (sub1 connectx)) 1] [(= (+ (helper-l right-o) (helper-l left-o)) (- connectx 2)) .85] [(= (+ (helper-l right-o) (helper-l left-o)) (- connectx 3)) .55] [(= (+ (helper-l right-o) (helper-l left-o)) (- connectx 4)) .3] [else 0])])) (define defense (cond [(and (helper-b right-d) (helper-b left-d)) (if (>= (+ (helper-l right-d) (helper-l left-d)) (sub1 connectx)) .9 0)] [(or (helper-b right-d) (helper-b left-d)) (cond [(>= (+ (helper-l right-d) (helper-l left-d)) (sub1 connectx)) .9] [(= (+ (helper-l right-d) (helper-l left-d)) (- connectx 2)) .25] [(= (+ (helper-l right-d) (helper-l left-d)) (- connectx 3)) .01] [else 0])] [else (cond [(>= (+ (helper-l right-d) (helper-l left-d)) (sub1 connectx)) .9] [(= (+ (helper-l right-d) (helper-l left-d)) (- connectx 2)) .8] [(= (+ (helper-l right-d) (helper-l left-d)) (- connectx 3)) .25] [(= (+ (helper-l right-d) (helper-l left-d)) (- connectx 4)) .02] [else 0])])) (define total-value (+ defense offense))] (make-space a-pos total-value offense defense))) ;streaker: num num symbol pos -> helper ;streaker is a pathetic little streak detector a wrapper function (define (streaker x y a-symbol a-pos board) (streaker-non-wrapper x y a-symbol (list (+ x (first a-pos)) (+ y (second a-pos))) 0 board)) ;streaker-non-wrapper: num num symbol pos -> helper ;streaker-non-wrapper returns the streak in one direction. (define (streaker-non-wrapper x y a-s a-p counter board) (cond [(symbol=? a-s (m-r a-p board)) (streaker-non-wrapper x y a-s (list (+ (first a-p) x) (+ (second a-p) y)) (add1 counter) board)] [(symbol=? (m-r a-p board) blank) (make-helper counter false)] [else (make-helper counter true)])) ;(compute-value (list 5 2) pbs-v1) ;(m-r (list 4 3) pbs-v1) ;compute-all-values: list of positions list of spaces board -> list of spaces ;compute-all-values literally takes the output from f-s and trasnumutates into something bigger and better! (namely the spaces and their values) (define (compute-all-values lop los board) (cond [(empty? lop) los] [else (compute-all-values (rest lop) (cons (compute-value (first lop) board) los) board)])) ;sort-moves: list of spaces -> list-of-spaces ;sort-moves returns the spaces in order of total move value. (define (sort-moves los) (local [(define answer (quicksort los (lambda (x y) (> (space-t-v x) (space-t-v y)))))] (if (<= (space-t-v (first answer)) 0) (middle-list-first answer (random (length answer))) answer))) ;middle-list-first: list num -> list ;returns the list with the first num items removed. (define (middle-list-first a-list num) (cond [(<= num 1) a-list] [else (middle-list-first (rest a-list) (sub1 num))])) ;(define fake-spaces (list (make-space (list 1 9) 3 .64 .64) (make-space (list 1 3) 1 .12 .32) (make-space (list 8 8) 8 .33 .64))) ;(sort-moves fake-spaces) ;death-or-life: list of spaces num position -> false or a position ;death-or-life returns false if there is no life-or-death situation, or the position to play in if there is a situation like that. (define (death-or-life los value a-pos) (cond [(empty? los) (if (> value .67) a-pos false)] [else (cond [(> (space-o-v (first los)) (space-d-v (first los))) (if (> (space-o-v (first los)) value) (death-or-life (rest los) (space-o-v (first los)) (space-position (first los))) (death-or-life (rest los) value a-pos))] [else (if (> (space-d-v (first los)) value) (death-or-life (rest los) (space-d-v (first los)) (space-position (first los))) (death-or-life (rest los) value a-pos))])])) ;dol: list-of-spaces -> false of a position ;wrapper function for death-or-life, look at death-or-life for purpose (define (dol los) (death-or-life los .66 (list 0 0))) ;(dol fake-spaces) ;control: -> position ;control does everything and returns the position to move at. (define (control) (local [(define board (lol-vov (getmove))) (define spaces (f-s board)) (define spaces-values (compute-all-values spaces empty board)) (define death-value (dol spaces-values))] (if (cons? death-value) (display-move death-value) (display-move (space-position (first (sort-moves spaces-values))))))) ;display-move: position -> (void) ;display-move displays the move I want to make in the correct format. (define (display-move a-pos) (printf "~s" (list (- (second a-pos) 1)(- (first a-pos) 1)))) ;(define spaces (f-s pbs-v1)) ;(define spaces-values (compute-all-values spaces empty pbs-v1)) ;(set! spaces-values (sort-moves spaces-values)) ;spaces-values (control)