a day's hacking with a whole bunch of stuff going on
This commit is contained in:
parent
8d12489acb
commit
7282958dcc
|
@ -0,0 +1,9 @@
|
||||||
|
#lang racket
|
||||||
|
|
||||||
|
; runs all the players against each other as both first and second player.
|
||||||
|
|
||||||
|
(require "main.rkt" "players.rkt")
|
||||||
|
|
||||||
|
(define all-players '(player-random player-first player-last))
|
||||||
|
|
||||||
|
(define matchups (append (combinations all-players 2) (map reverse (combinations all-players 2))))
|
2
gui.rkt
2
gui.rkt
|
@ -50,7 +50,7 @@
|
||||||
[label "&Load"]
|
[label "&Load"]
|
||||||
[parent file-menu]
|
[parent file-menu]
|
||||||
[callback (lambda (m event)
|
[callback (lambda (m event)
|
||||||
(let ([f (get-file "Load Game")]) ;#f #f #f ".dbn" '() '(("*.dbn" "Dots and Boxes Notation")))])
|
(let ([f (get-file "Load Game" #f #f #f ".dbn" '() '(("Dots and Boxes Notation" "*.dbn")))])
|
||||||
(if (eq? #f f) 0 (load-game-gui! (load-game! f)))
|
(if (eq? #f f) 0 (load-game-gui! (load-game! f)))
|
||||||
(send grid-canvas refresh)
|
(send grid-canvas refresh)
|
||||||
(send log set (map line->string g))
|
(send log set (map line->string g))
|
||||||
|
|
101
main.rkt
101
main.rkt
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
(provide (all-defined-out)) ; for testing module
|
(provide (all-defined-out)) ; for testing module
|
||||||
|
|
||||||
(require racket/draw racket/random)
|
(require racket/draw racket/random file/gif)
|
||||||
|
|
||||||
; a Grid contains:
|
; a Grid contains:
|
||||||
; -- a list of lines. All lines in a grid must be specified as moving left to right, top to bottom ("to" coordinate higher than "from" coordinate")
|
; -- a list of lines. All lines in a grid must be specified as moving left to right, top to bottom ("to" coordinate higher than "from" coordinate")
|
||||||
|
@ -122,15 +122,6 @@
|
||||||
(not (out-of-bounds? (line-from line) grid))
|
(not (out-of-bounds? (line-from line) grid))
|
||||||
(not (out-of-bounds? (line-to line) grid)))))
|
(not (out-of-bounds? (line-to line) grid)))))
|
||||||
|
|
||||||
; a Player that plays random moves
|
|
||||||
(define random-player
|
|
||||||
(player
|
|
||||||
"Random"
|
|
||||||
(lambda (g n)
|
|
||||||
(let ([m (car (random-sample (valid-moves g) 1))])
|
|
||||||
(line (line-from m) (line-to m) n)))))
|
|
||||||
|
|
||||||
|
|
||||||
; Grid Line -> Grid
|
; Grid Line -> Grid
|
||||||
; adds line to grid, if it is a valid move. Otherwise skips the move.
|
; adds line to grid, if it is a valid move. Otherwise skips the move.
|
||||||
(define (append-move g l)
|
(define (append-move g l)
|
||||||
|
@ -209,10 +200,46 @@
|
||||||
(define (start-game p1 p2 grid1 grid2)
|
(define (start-game p1 p2 grid1 grid2)
|
||||||
(play-game (GameState (grid '() grid1 grid2) 0 '(0 0) (list p1 p2))))
|
(play-game (GameState (grid '() grid1 grid2) 0 '(0 0) (list p1 p2))))
|
||||||
|
|
||||||
|
; GameState path !
|
||||||
|
; saves a game into the .dbn file format that I just made up.
|
||||||
|
; don't worry, it's sexpy.
|
||||||
|
(define (save-game! s filename)
|
||||||
|
(let ([g (GameState-grid s)]
|
||||||
|
[f (open-output-file filename)])
|
||||||
|
(pretty-write
|
||||||
|
`((player0 ,(player-name (first (GameState-players s))))
|
||||||
|
(player1 ,(player-name (second (GameState-players s))))
|
||||||
|
(grid ,(grid-width g) ,(grid-height g))
|
||||||
|
(score ,(first (GameState-scores s)) ,(second (GameState-scores s)))
|
||||||
|
(lines
|
||||||
|
,(for/list ([l (grid-lines g)])
|
||||||
|
(list (point-x (line-from l)) (point-y (line-from l)) (point-x (line-to l)) (point-y (line-to l)) (line-player l))))) f)
|
||||||
|
(close-output-port f)))
|
||||||
|
|
||||||
|
; path -> GameState
|
||||||
|
; loads a game from a .dbn file into a GameState structure
|
||||||
|
(define (load-game! p)
|
||||||
|
(let* ([f (open-input-file p)]
|
||||||
|
[data (read f)])
|
||||||
|
(close-input-port f)
|
||||||
|
(GameState
|
||||||
|
(grid
|
||||||
|
(for/list ([i (last (assoc 'lines data))])
|
||||||
|
(line (point (first i) (second i)) (point (third i) (fourth i)) (fifth i)))
|
||||||
|
(second (assoc 'grid data)) (last (assoc 'grid data)))
|
||||||
|
0 ; assumed, the game is over
|
||||||
|
(list (second (assoc 'score data)) (last (assoc 'score data)))
|
||||||
|
`(
|
||||||
|
,(player (last (assoc 'player0 data)) 0)
|
||||||
|
,(player (last (assoc 'player1 data)) 0)
|
||||||
|
))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; Grid -> Image
|
; Grid -> Image
|
||||||
; renders grid to an image for showing humans the game.
|
; renders grid to an image for showing humans the game.
|
||||||
(define (render-grid-bitmap g)
|
(define (render-grid-bitmap g)
|
||||||
(let* ([bitmap (make-bitmap (+ 10 (* (grid-width g) GRID-SCALE) (+ 10 (* (grid-width g) GRID-SCALE))))] ; add border for printing
|
(let* ([bitmap (make-bitmap (+ 10 (* (grid-width g) GRID-SCALE)) (+ 10 (* (grid-width g) GRID-SCALE)))] ; add border for printing
|
||||||
[dc (new bitmap-dc% [bitmap bitmap])])
|
[dc (new bitmap-dc% [bitmap bitmap])])
|
||||||
(render-grid g dc)
|
(render-grid g dc)
|
||||||
bitmap))
|
bitmap))
|
||||||
|
@ -241,36 +268,24 @@
|
||||||
0))))
|
0))))
|
||||||
(send dc draw-bitmap (grid-dots (grid-width g) (grid-height g)) 0 0)) ; overlay dot grid
|
(send dc draw-bitmap (grid-dots (grid-width g) (grid-height g)) 0 0)) ; overlay dot grid
|
||||||
|
|
||||||
; GameState path !
|
; GameState filepath !
|
||||||
; saves a game into the .dbn file format that I just made up.
|
; saves a game's history as images into /tmp/
|
||||||
; don't worry, it's sexpy.
|
; TODO learn file/gif and make the gif properly
|
||||||
(define (save-game! s filename)
|
(define (game->images game)
|
||||||
(let ([g (GameState-grid s)]
|
(let* ([g (GameState-grid game)]
|
||||||
[f (open-output-file filename)])
|
[frames (grid-frames (grid '() (grid-width g) (grid-height g)) g '())])
|
||||||
(pretty-write
|
|
||||||
`((player0 ,(player-name (first (GameState-players s))))
|
(for ([frame (in-range (length frames))])
|
||||||
(player1 ,(player-name (second (GameState-players s))))
|
(send (list-ref frames frame) save-file (format "/tmp/dotsandboxes~a.png" frame) 'png)
|
||||||
(grid ,(grid-width g) ,(grid-height g))
|
)))
|
||||||
(score ,(first (GameState-scores s)) ,(second (GameState-scores s)))
|
|
||||||
(lines
|
|
||||||
,((for/list ([l (grid-lines g)])
|
|
||||||
(list (point-x (line-from l)) (point-y (line-from l)) (point-x (line-to l)) (point-y (line-to l)) (line-player l)))))) f)
|
|
||||||
(close-output-port f)))
|
|
||||||
|
|
||||||
; path -> GameState
|
; Used internally for rendering all the frames from a grid's history
|
||||||
; loads a game from a .dbn file into a GameState structure
|
(define (grid-frames g grid-in frames)
|
||||||
(define (load-game! p)
|
(cond
|
||||||
(let* ([f (open-input-file p)]
|
[(empty? (grid-lines grid-in)) frames]
|
||||||
[data (read f)])
|
[(grid-frames
|
||||||
(close-input-port f)
|
(grid (append (grid-lines g) (list (car (grid-lines grid-in)))) (grid-width g) (grid-height g))
|
||||||
(GameState
|
(grid (cdr (grid-lines grid-in)) (grid-width grid-in) (grid-height grid-in))
|
||||||
(grid
|
(append frames (list (render-grid-bitmap g))))]
|
||||||
(for/list ([i (last (assoc 'lines data))])
|
))
|
||||||
(line (point (first i) (second i)) (point (third i) (fourth i)) (fifth i)))
|
|
||||||
(second (assoc 'grid data)) (last (assoc 'grid data)))
|
|
||||||
0 ; assumed, the game is over
|
|
||||||
(list (second (assoc 'score data)) (last (assoc 'score data)))
|
|
||||||
`(
|
|
||||||
,(player (last (assoc 'player0 data)) 0)
|
|
||||||
,(player (last (assoc 'player1 data)) 0)
|
|
||||||
))))
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#lang racket
|
||||||
|
|
||||||
|
; dots and boxes players!
|
||||||
|
|
||||||
|
(require "main.rkt" racket/random)
|
||||||
|
|
||||||
|
(provide player-random player-first player-last)
|
||||||
|
|
||||||
|
; a Player that plays random moves
|
||||||
|
(define player-random
|
||||||
|
(player
|
||||||
|
"Random"
|
||||||
|
(lambda (g n)
|
||||||
|
(let ([m (car (random-sample (valid-moves g) 1))])
|
||||||
|
(line (line-from m) (line-to m) n)))))
|
||||||
|
|
||||||
|
; plays the first valid move found
|
||||||
|
(define player-first
|
||||||
|
(player
|
||||||
|
"First Move"
|
||||||
|
(lambda (g n)
|
||||||
|
(let ([m (first (valid-moves g))])
|
||||||
|
(line (line-from m) (line-to m) n)))))
|
||||||
|
|
||||||
|
; plays the last valid move found
|
||||||
|
(define player-last
|
||||||
|
(player
|
||||||
|
"Last Move"
|
||||||
|
(lambda (g n)
|
||||||
|
(let ([m (last (valid-moves g))])
|
||||||
|
(line (line-from m) (line-to m) n)))))
|
Loading…
Reference in New Issue