;;; ;;; ICFPC 2012 Simulator ;;; (define $RobotState (type {[,$val [] {[$tgt (if (eq? tgt val) {[]} {})]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [_ [Something] {[$tgt {tgt}]}] })) (define $Tile (type {[ [] {[ (if ((= RobotState) pState state) {[]} {})] [_ {}]}] [ [RobotState] {[ {state}] [_ {}]}] [ [] {[ (if (eq? pFlag flag) {[]} {})] [_ {}]}] [ [Bool] {[ {[flag]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [_ [Something] {[$tgt {tgt}]}] })) (define $show-tile (lambda [$tile] (match tile Tile {[ "R"] [ "*"] [ "#"] [ "\\"] [ "."] [ " "] [ "O"] [ "L"]}))) (define $char-to-tile (lambda [$c] (match c Char {[,'R' >] [,'*' ] [,'#' ] [,'\\' ] [,'.' ] [,' ' ] [,'O' ] [,'L' ] }))) (define $Mine (Array Tile)) (define $Move (type {[ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [ [] {[ {[]}] [_ {}]}] [_ [Something] {[$tgt {tgt}]}] })) (define $char-to-move (lambda [$c] (match c Char {[,'L' ] [,'R' ] [,'U' ] [,'D' ] [,'W' ] [,'A' ] [,'h' ] [,'l' ] [,'k' ] [,'j' ] }))) (define $Point [Integer Integer]) (define $GameState (type {[ [Mine Integer Integer Integer] {[ {[mine step score lambda-count]}]}] [_ [Something] {[$tgt {tgt}]}] })) (define $get-mine (lambda [$game-state] (match game-state GameState {[ mine]}))) (define $show-mine (lambda [$mine] (let {[$kss (keys-for-display (array-range mine))]} (foldl string-append "" (map (lambda [$ks] (string-append (foldl string-append "" (map (lambda [$k] (show-tile (array-ref k mine))) ks)) "\n")) kss))))) (define $get-robot-state (lambda [$mine] (let {[$rp ((find-from-value-with-pattern Tile) mine)]} (match (array-ref rp mine) Tile {[ state]})))) (define $move-robot (lambda [$mine $move] (generate-array (lambda [$x $y] (match move Move {[ (match mine Mine { [(& > >) ] [(& > >) >] [(& > >) ] [(& > >) >] [(& > (| ^ )> (& > >))) ] [(& > (| ^ )> (& > >))) >] [(& > > >) ] [> >] [ tile]})] [ (match mine Mine { [(& > >) ] [(& > >) >] [(& > >) ] [(& > >) >] [(& > (| ^ )> (& > >))) ] [(& > (| ^ )> (& > >))) >] [(& > > >) ] [> >] [ tile]})] [ (match mine Mine { [(& > >) ] [(& > >) >] [(& > >) ] [(& > >) >] [(& > ^ )>) ] [(& > ^ )>) >] [> >] [ tile]})] [ (match mine Mine { [(& > >) ] [(& > >) >] [(& > >) ] [(& > >) >] [(& > ^ )>) ] [(& > ^ )>) >] [> >] [ tile]})] [ (match mine Mine {[> >] [ tile]})] [ (match mine Mine {[> >] [ tile]})] })) (array-range mine)))) (define $update-map (lambda [$mine] (generate-array (lambda [$x $y] (match mine Mine {[(& > >) ] [(& > >) ] [(& > )> > >) ] [(& > )> > >) ] [(& > > (| > >) > >) ] [(& > > (| > >) > >) ] [> (if (eq? 0 (size (lambda-stones mine))) )] [> ] [ tile] })) (array-range mine)))) (define $lambda-stones (lambda [$mine] (concat (map (lambda [$x $y] (match mine Mine {[> {[x y]}] [_ {}]})) (array-keys mine))))) (define $ending-update (lambda [$mine] (generate-array (lambda [$x $y] (match mine Mine {[(& > >) >] [ tile] })) (array-range mine)))) (define $ending? (lambda [$mine] (match (get-robot-state mine) RobotState {[(| ) #t] [_ #f]}))) (define $calc-score (lambda [$game-state] (match game-state GameState {[ (match (get-robot-state mine) RobotState {[ (+ score (* 25 lambda-count))] [ score] [ 0]})]}))) (define $generate-mine (lambda [$lines] (do {[$tss (map (lambda [$line] (map char-to-tile (string-to-chars line))) (reverse lines))] [$mx (max (map size tss))] [$my (size tss)] [$tss2 (map (lambda [$cs] {@cs @(loop $l $i (between 1 (- mx (size cs))) { @l} {})}) tss)] } (letrec {[$rotate (lambda [$tss] (match (car tss) (List Something) {[ {}] [_ {(map car tss) @(rotate (map cdr tss))}]}))]} (let {[$tss3 (rotate tss2)]} (generate-array (lambda [$x $y] (nth y (nth x tss3))) [mx my])))))) (define $main (lambda [$world $argv] (match argv (List String) {[> (do {[[$world $port] (open-input-file world file)] } (letrec {[$readMapLoop (lambda [$world $lines] (do {[[$world $line] (read-line-from-port world port)]} (if (or (eof? line) (eq-s? line "")) [world lines] (readMapLoop world {@lines line}))))] } (do {[[$world $lines] (readMapLoop world {})] [$init-mine (generate-mine lines)] [$init-state ]} (letrec {[$interactive (lambda [$world $game-state] (match game-state GameState {[ (do { [$world (write-string world (show-mine mine))] [$world (write-char world '\n')] [$world (write-string world "robot-state: ")] [$world (write world (get-robot-state mine))] [$world (write-char world '\n')] [$world (write-string world "lambda-count: ")] [$world (write world lambda-count)] [$world (write-char world '\n')] [$world (write-string world "score: ")] [$world (write world score)] [$world (write-char world '\n')] [$world (write-string world "command: ")] [$world (flush world)] [[$world $cmd] (read-char world)] [$world (write-char world '\n')] [$world (flush world)] [$move (char-to-move cmd)] [$mine2 (ending-update (update-map (move-robot mine move)))] [$game-state2 (get-robot-state mine2)) (- (+ 50 score) 1) (- score 1)) (if ((= RobotState) (get-robot-state mine2)) (+ 1 lambda-count) lambda-count) >] } (if (ending? mine2) (do { [$world (write-string world (show-mine mine2))] [$world (write-char world '\n')] [$world (write-string world "robot-state: ")] [$world (write world (get-robot-state mine2))] [$world (write-char world '\n')] [$world (write-string world "score: ")] [$world (write world (calc-score game-state2))] [$world (write-char world '\n')] } world) (interactive world game-state2)))]}))]} (interactive world init-state)))))] [_ (do { [$world (write-string world "usage: mine FILENAME (specify map file)\n")] } world)]})))