Check-in Differences
Not logged in

Difference From:

[bee0596f0f] Refactoring. (user: kinaba, tags: trunk, date: 2012-07-14 11:24:30)

To:

[fc9286dad1] uum (user: kinaba, tags: redesign, date: 2012-07-15 12:11:33)

Added maps/100x100.map version [5beaf6fad4143830]

> 1 ################################################################################ > 2 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 3 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 4 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 5 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 6 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\L\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 7 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 8 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 9 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 10 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 11 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 12 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 13 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 14 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 15 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 16 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 17 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 18 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 19 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 20 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 21 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 22 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 23 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 24 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 25 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 26 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 27 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 28 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 29 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 30 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 31 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 32 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 33 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 34 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 35 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 36 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 37 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 38 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 39 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 40 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 41 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 42 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 43 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 44 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 45 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 46 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 47 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 48 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 49 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 50 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 51 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 52 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 53 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 54 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 55 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 56 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 57 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 58 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 59 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 60 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 61 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 62 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\R\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 63 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 64 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. > 65 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* > 66 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 67 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 68 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 69 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 70 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 71 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 72 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. > 73 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* > 74 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 75 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 76 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 77 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 78 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 79 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 80 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 81 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 82 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 83 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 84 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 85 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 86 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. > 87 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* > 88 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 89 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 90 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 91 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 92 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 93 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 94 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 95 #************************\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 96 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.********************************\.\.\.\.\.\.\.\.\. > 97 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.************* > 98 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\. > 99 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\ > 100 ################################################################################

Added maps/40x40.map version [06dc362ef16f425d]

> 1 ######################################## > 2 #L\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 3 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 4 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# > 5 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 6 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 7 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 8 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 9 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 10 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 11 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# > 12 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 13 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 14 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 15 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 16 #.\.\.\.\.\.\.\.\.\W\.\.\.\.\.\.\.\.\.\# > 17 #.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*# > 18 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 19 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 20 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 21 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 22 #.\.\.\.\!\.\.\.\.\.\.\.\W\.\.\.\.\.\.\# > 23 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 24 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 25 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 26 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 27 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 28 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 29 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 30 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 31 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\!\.\.# > 32 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 33 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 34 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\# > 35 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\!\.\.# > 36 #.\.\.\.\.\.\.\.\W\.\.\.\.\.\.\.\.\.\.\# > 37 #\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.# > 38 #.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.\.R# > 39 ######################################## > 40 > 41 Flooding 80

Added maps/beard1.map version [bb6926793a51311a]

> 1 ########## > 2 #** \\\\# > 3 #.R.. # > 4 # \ ..*\# > 5 #! ..*!# > 6 #### # # > 7 #\\... # L > 8 #\\.W... # > 9 #\\. # > 10 ########## > 11 > 12 Growth 15 > 13 Razors 0

Added maps/beard2.map version [2e942009c89717d7]

> 1 ############################## > 2 #R...........................# > 3 #.........................W..# > 4 #..\\\\\\\\\\\\\\\\\\\\\\\\..# > 5 #............................# > 6 #..*****.*\...*...*...*****..# > 7 #..*\....*\....*\*..*.\\*\\..# > 8 #..*\....****..!*!......*....# > 9 #..*\....*\....*\*..*...*....# > 10 #..*\....*\...*...*.....*....# > 11 #............................# > 12 #..\\\\\\\\\\\\\\\\\\\\\\\\..# > 13 #................ ..... .....# > 14 #................ W....L# > 15 ############################## > 16 > 17 Growth 25 > 18 Razors 10 > 19 Flooding 20

Added maps/beard3.map version [1dcab340493857d0]

> 1 ################ > 2 #*****#!! 1 # > 3 #..\..# # > 4 #########\\\\ # .\\\. # > 5 #.............# * # > 6 #.. .\\\#..!..#\** # > 7 #.. LW\\#W ..##### #### > 8 #..R\\\\#.. ..*\*\*W...# > 9 #.......A.. ...\.\...\\# > 10 #.......... ** # > 11 ############....\.###### > 12 #.....!# > 13 ######## > 14 > 15 Growth 10 > 16 Trampoline A targets 1

Added maps/beard4.map version [b62967eb47a5f507]

> 1 #################### > 2 #W\\!#\\\**.\#W\\\W# > 3 ##*######..###..\\\# > 4 #.......\.R ###...\# > 5 #####.###.#.......## > 6 #.......#.#\####.### > 7 #\\##\###\#\\#...#.L > 8 #\##\.###.####.#.#.# > 9 #\W#####.....###.W.# > 10 ####\\...\\\...#.#.# > 11 #W*######.######.#.# > 12 #\\\\\\\\\.........# > 13 ############\###\### > 14 #\\.. *..........\\# > 15 #W... #.........##W# > 16 ####################

Added maps/fun1.map version [2f7f87a4d02c6448]

> 1 \\\\\\\\\L > 2 ********** > 3 > 4 > 5 > 6 > 7 > 8 R

Added maps/trampoline1.map version [5af697c0003d5516]

> 1 ############ > 2 #..*.R..*..# > 3 #..A....B..###### > 4 #....2.. ..#\\\C# > 5 #......* *.#\\\1# > 6 ########L######## > 7 > 8 Trampoline A targets 1 > 9 Trampoline B targets 1 > 10 Trampoline C targets 2

Added maps/trampoline2.map version [288f9d055c2777fa]

> 1 ###### > 2 #....# > 3 #.**.# > 4 #.**.# > 5 #.**.# > 6 ######.\\.###### > 7 #**....*.......# > 8 #\\....L\\\....# > 9 #A......*****..# > 10 ######R.....########### > 11 ###.....*.....\\\# > 12 #\\\\#..1...\\\# > 13 #\\\\#......\\\# > 14 ################ > 15 > 16 Trampoline A targets 1

Added maps/trampoline3.map version [7fcf90c1ca373c41]

> 1 ####################################### > 2 #****................#..1...\\\\\\\B..# > 3 #R.......############################## > 4 #.. ..................................# > 5 #.. ........ \ ......# > 6 #.. .*. ....**.*...#....... ..........# > 7 #.. ... ....\\\\...#.A..... ..........# > 8 #.. ... ....\ .....#....... * \\..# > 9 #.. ... ....\......#....... ..........# > 10 #.. ... ....\......#....... ..........# > 11 #.. ... ...........#................**# > 12 #..\\\\\...........#................\\# > 13 ########### ############## ############ > 14 #...*.................................# > 15 #....*.................. ......# > 16 #... .*....*.............. ..... .....# > 17 #....*2*........########.. ..... .....L > 18 #...*...*.......#\\\#..... ...*.......# > 19 #.....\\\.......#\\\#....**..***......# > 20 #.... .......#\\\#*................# > 21 #...............#\\\#*...**...*.......# > 22 #...............#.....................# > 23 ###### ############## ### ####### > 24 #\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\# > 25 ####################################### > 26 > 27 Trampoline A targets 1 > 28 Trampoline B targets 2 > 29

Added score_memo.txt version [95f0626c958d6d31]

> 1 contest1 212! > 2 contest2 280? > 3 contest3 275! > 4 contest4 561? > 5 contest5 1281? > 6 contest6 737 // deadend trap > 7 contest7 867? > 8 contest8 1245 // tricky > 9 contest9 3042? > 10 contest10 2076 // * on lambda, must move * first > 11 flood1 569 // too slow, because of 1-left danger lambda > 12 flood2 280? > 13 flood3 802 // too slow, drown > 14 flood4 970 // incorrect order of digging > 15 flood5 561? > 16 trampoline1 291 // * on trampoline. must move * first > 17 trampoline2 1728? > 18 trampoline3 698 // * on trampoline target. must move * first. > 19 beard1 856? > 20 beard2 2792 // hutsu-ni muzui > 21 beard3 811 // tricky. must hurry to cut hige. > 22 beard4 677 // deadend trap

Added src/Makefile version [01a4f7a0531dae71]

> 1 # To build, the following packages are needed. > 2 # wget http://ftp.digitalmars.com/dmd_2.059-0_i386.deb > 3 # sudo apt-get install gcc gcc-multilib > 4 # sudo pkg -i dmd_2.059-0_i386.deb > 5 > 6 all: > 7 dmd -O -release -inline -oflifter cui_auto_main.d driver.d game.d output

Added src/cui_auto_main.d version [b38d60ea39d11e6e]

> 1 import util; > 2 import game; > 3 import output; > 4 import driver; > 5 import solver; > 6 > 7 class CUI(Solver) : GameObserver > 8 { > 9 this(in Game g) { solver = new Solver(g); } > 10 Solver solver; > 11 bool fin; > 12 override void on_game_changed(char c, in Game g, bool finished) > 13 { > 14 fin = finished; > 15 } > 16 } > 17 > 18 void main(string[] args) > 19 { > 20 Driver d = new Driver(stdin); > 21 d.addObserver!(GuardedOutput)(); > 22 auto c = d.addObserver!(CUI!MainSolver)(); > 23 while(!c.fin) > 24 d.command(c.solver.single_step()); > 25 }

Added src/driver.d version [3d15ff20e76164b8]

> 1 import game; > 2 import util; > 3 > 4 interface GameObserver > 5 { > 6 // this(in Game g); > 7 void on_game_changed(char c, in Game g, bool finished); > 8 } > 9 > 10 class Driver > 11 { > 12 this(Game g) { this.game = g; } > 13 this(File game_data) { this(new Game(game_data)); } > 14 > 15 void command(char c) > 16 { > 17 if( finished ) > 18 return; > 19 if( c == 'A' ) > 20 aborted = true; > 21 else > 22 game.command(c); > 23 foreach(ob; observers) > 24 ob.on_game_changed(c, game, finished); > 25 } > 26 > 27 T addObserver(T)() > 28 { > 29 T t = new T(game); > 30 observers ~= t; > 31 return t; > 32 } > 33 > 34 @property bool finished() > 35 { > 36 return game.cleared || game.dead || aborted; > 37 } > 38 > 39 private: > 40 Game game; > 41 GameObserver[] observers; > 42 bool aborted = false; > 43 } > 44 > 45 unittest > 46 { > 47 static class MockGame : Game { > 48 this() { super(null,null,null); } > 49 string log; > 50 void command(char c) { log ~= c; } > 51 } > 52 static class MockObserver : GameObserver { > 53 string log; > 54 this(in Game g) {} > 55 void on_game_changed(char c, in Game g, bool fin) { log~=c; if(f > 56 } > 57 > 58 auto g = new MockGame; > 59 auto d = new Driver(g); > 60 auto o = d.addObserver!MockObserver(); > 61 foreach(char c; "UDLRSAUDLRSA") > 62 d.command(c); > 63 assert(g.log == "UDLRS"); > 64 assert(o.log == "UDLRSA$"); > 65 }

Modified src/game.d from [cde4121762ca0c01] to [fc05481901940844].

4 4 5 class Pos 5 class Pos 6 { 6 { 7 public immutable int y, x; 7 public immutable int y, x; 8 mixin DeriveCreate; 8 mixin DeriveCreate; 9 mixin DeriveCompare; 9 mixin DeriveCompare; 10 mixin DeriveShow; 10 mixin DeriveShow; 11 Pos clone() const { return new Pos(y, x); } | 11 Pos clone() const { return cast(Pos) this; } 12 12 13 @property: 13 @property: 14 Pos wait() { return this.clone(); } 14 Pos wait() { return this.clone(); } 15 Pos up() { return new Pos(y+1, x); } 15 Pos up() { return new Pos(y+1, x); } 16 Pos down() { return new Pos(y-1, x); } 16 Pos down() { return new Pos(y-1, x); } 17 Pos left() { return new Pos(y, x-1); } 17 Pos left() { return new Pos(y, x-1); } 18 Pos right() { return new Pos(y, x+1); } 18 Pos right() { return new Pos(y, x+1); } ................................................................................................................................................................................ 41 41 42 class Water 42 class Water 43 { 43 { 44 public immutable int base, pace; 44 public immutable int base, pace; 45 mixin DeriveCreate; 45 mixin DeriveCreate; 46 mixin DeriveCompare; 46 mixin DeriveCompare; 47 mixin DeriveShow; 47 mixin DeriveShow; 48 Water clone() const { return new Water(base, pace); } | 48 Water clone() const { return cast(Water)this; } 49 49 50 static load(string[string] params) 50 static load(string[string] params) 51 { 51 { 52 return new Water( < 53 params.get("Water", "0").to!int(), | 52 return new Water(params.get("Water", "0").to!int(), 54 params.get("Flooding", "0").to!int() | 53 params.get("Flooding", "0").to!int()); 55 ); < 56 } 54 } 57 55 58 int level(int number_of_update) const 56 int level(int number_of_update) const 59 { 57 { 60 return pace ? base+(number_of_update/pace) : base; 58 return pace ? base+(number_of_update/pace) : base; 61 } 59 } 62 60 ................................................................................................................................................................................ 84 assert( 1 == w.level(3) ); 82 assert( 1 == w.level(3) ); 85 assert( 1 == w.level(4) ); 83 assert( 1 == w.level(4) ); 86 assert( 1 == w.level(5) ); 84 assert( 1 == w.level(5) ); 87 } 85 } 88 86 89 //////////////////////////////////////////////////////////////////////////////// 87 //////////////////////////////////////////////////////////////////////////////// 90 88 > 89 class Hige > 90 { > 91 public immutable int pace; > 92 mixin DeriveCreate; > 93 mixin DeriveCompare; > 94 mixin DeriveShow; > 95 Hige clone() const { return cast(Hige)this; } > 96 > 97 static load(string[string] params) > 98 { > 99 return new Hige(params.get("Growth", "25").to!int()); > 100 } > 101 > 102 bool is_growing_turn(int turn) const > 103 { > 104 return pace ? turn%pace == pace-1 : false; > 105 } > 106 > 107 int until_rise(int turn) const > 108 { > 109 return pace ? pace-turn%pace : int.max; > 110 } > 111 } > 112 > 113 //////////////////////////////////////////////////////////////////////////////// > 114 91 class Map 115 class Map 92 { 116 { 93 mixin DeriveShow; 117 mixin DeriveShow; 94 118 95 static Map load(string[] raw_data, string[string] params) | 119 static Map load(string[] raw_data, string[string] params, char[char] tra 96 { 120 { 97 // TODO: choose optimal representation. 121 // TODO: choose optimal representation. 98 return new Map(raw_data, params); | 122 return new Map(raw_data, params, trampo); 99 } 123 } 100 124 101 char[][] data; 125 char[][] data; 102 Pos robot; 126 Pos robot; 103 Pos lift; 127 Pos lift; 104 int waterproof; 128 int waterproof; > 129 Pos[char] tr_target; > 130 Pos[][char] tr_source; > 131 const(Hige) hige; > 132 int razor; 105 133 106 Map clone() const { return new Map(this); } 134 Map clone() const { return new Map(this); } 107 this(const(Map) m) { | 135 this(in Map m) { 108 foreach(s; m.data) 136 foreach(s; m.data) 109 this.data ~= s.dup; 137 this.data ~= s.dup; 110 this.robot = m.robot.clone(); 138 this.robot = m.robot.clone(); 111 this.lift = m.lift.clone(); 139 this.lift = m.lift.clone(); 112 this.waterproof = m.waterproof; 140 this.waterproof = m.waterproof; > 141 this.tr_target = cast(Pos[char])m.tr_target; > 142 this.tr_source = cast(Pos[][char])m.tr_source; > 143 this.hige = m.hige.clone(); > 144 this.razor = m.razor; 113 } 145 } 114 146 115 this(string[] raw_data, string[string] params) | 147 this(string[] raw_data, string[string] params, char[char] trampo) 116 { 148 { 117 int width = 0; 149 int width = 0; 118 foreach(r; raw_data) 150 foreach(r; raw_data) 119 width = max(width, r.length); 151 width = max(width, r.length); 120 foreach(r; raw_data) { 152 foreach(r; raw_data) { 121 this.data ~= r.dup; 153 this.data ~= r.dup; 122 this.data[$-1].length = width; 154 this.data[$-1].length = width; ................................................................................................................................................................................ 126 for(int y=1; y<=H; ++y) 158 for(int y=1; y<=H; ++y) 127 for(int x=1; x<=W; ++x) { 159 for(int x=1; x<=W; ++x) { 128 if(this[y,x] == 'R') 160 if(this[y,x] == 'R') 129 this.robot = new Pos(y,x); 161 this.robot = new Pos(y,x); 130 if(this[y,x] == 'L' || this[y,x] == 'O') 162 if(this[y,x] == 'L' || this[y,x] == 'O') 131 this.lift = new Pos(y,x); 163 this.lift = new Pos(y,x); 132 } 164 } > 165 > 166 Pos[char] tr_pos; > 167 for(int y=1; y<=H; ++y) > 168 for(int x=1; x<=W; ++x) { > 169 char c = this[y,x]; > 170 if('1'<=c && c<='9' || 'A'<=c&&c<='I') > 171 tr_pos[c] = new Pos(y,x); > 172 } 133 173 134 this.waterproof = params.get("Waterproof", "5").to!int(); 174 this.waterproof = params.get("Waterproof", "5").to!int(); > 175 foreach(fr,to; trampo) { > 176 tr_target[fr] = tr_pos[to]; > 177 if(to !in tr_source) tr_source[to] = []; > 178 tr_source[to] ~= tr_pos[fr]; > 179 } > 180 > 181 this.hige = Hige.load(params); > 182 this.razor = params.get("Razors", "0").to!int(); 135 } 183 } 136 184 137 const @property { 185 const @property { 138 int H() { return data.length; } 186 int H() { return data.length; } 139 int W() { return data[0].length; } 187 int W() { return data[0].length; } 140 } 188 } 141 189 ................................................................................................................................................................................ 145 // Adjust coordinate to the spec. bottom-left is (1,1). 193 // Adjust coordinate to the spec. bottom-left is (1,1). 146 --y, --x; 194 --y, --x; 147 if(y<0||H<=y||x<0||W<=x) 195 if(y<0||H<=y||x<0||W<=x) 148 return '#'; 196 return '#'; 149 return data[H-1-y][x]; 197 return data[H-1-y][x]; 150 } 198 } 151 199 152 char opIndex(Pos p) | 200 char opIndex(in Pos p) 153 { 201 { 154 return this[p.y, p.x]; 202 return this[p.y, p.x]; 155 } 203 } 156 } 204 } 157 205 158 void opIndexAssign(char c, int y, int x) 206 void opIndexAssign(char c, int y, int x) 159 { 207 { ................................................................................................................................................................................ 160 // Adjust coordinate to the spec. bottom-left is (1,1). 208 // Adjust coordinate to the spec. bottom-left is (1,1). 161 --y, --x; 209 --y, --x; 162 if(y<0||H<=y||x<0||W<=x) 210 if(y<0||H<=y||x<0||W<=x) 163 return; 211 return; 164 data[H-1-y][x] = c; 212 data[H-1-y][x] = c; 165 } 213 } 166 214 167 void opIndexAssign(char c, Pos p) | 215 void opIndexAssign(char c, in Pos p) 168 { 216 { 169 this[p.y, p.x] = c; 217 this[p.y, p.x] = c; 170 } 218 } 171 219 172 Pos[] lambdas() { | 220 Pos[] objects(char c) const { 173 Pos[] ans; 221 Pos[] ans; 174 for(int y=1; y<=H; ++y) 222 for(int y=1; y<=H; ++y) 175 for(int x=1; x<=W; ++x) 223 for(int x=1; x<=W; ++x) 176 if(this[y,x] == '\\') | 224 if(this[y,x] == c) 177 ans ~= new Pos(y,x); 225 ans ~= new Pos(y,x); 178 return ans; 226 return ans; 179 } 227 } 180 228 > 229 Pos[] razors() const { return objects('!'); } > 230 Pos[] lambdas() const { return objects('\\'); } > 231 181 bool cleared() | 232 bool cleared() const 182 { 233 { 183 for(int y=1; y<=H; ++y) 234 for(int y=1; y<=H; ++y) 184 for(int x=1; x<=W; ++x) 235 for(int x=1; x<=W; ++x) 185 if(this[y,x] == 'L' || this[y,x] == 'O') 236 if(this[y,x] == 'L' || this[y,x] == 'O') 186 return false; 237 return false; 187 return true; 238 return true; 188 } 239 } 189 240 190 Tuple!(int,bool) command(char c) | 241 Tuple!(int,bool) command(char c, int turn) 191 { 242 { > 243 assert( this[robot] == 'R' ); 192 if(c=='R') return move( 0, +1); | 244 if(c=='R') return move( 0, +1, turn); 193 if(c=='L') return move( 0, -1); | 245 if(c=='L') return move( 0, -1, turn); 194 if(c=='U') return move(+1, 0); | 246 if(c=='U') return move(+1, 0, turn); 195 if(c=='D') return move(-1, 0); | 247 if(c=='D') return move(-1, 0, turn); 196 if(c=='W') return move( 0, 0); | 248 if(c=='W') return move( 0, 0, turn); > 249 if(c=='S') return use_razor(turn); 197 assert(false); 250 assert(false); 198 } 251 } 199 252 > 253 Tuple!(int, bool) use_razor(int turn) > 254 { > 255 if(razor) { > 256 razor--; > 257 for(int dy=-1; dy<=+1; ++dy) > 258 for(int dx=-1; dx<=+1; ++dx) > 259 if(this[robot.y+dy,robot.x+dx] == 'W') > 260 this[robot.y+dy,robot.x+dx] = ' '; > 261 } > 262 > 263 bool dead = update(turn); > 264 return tuple(0,dead); > 265 } > 266 200 Tuple!(int, bool) move(int dy, int dx) | 267 Tuple!(int, bool) move(int dy, int dx, int turn) 201 { 268 { 202 int y = robot.y; 269 int y = robot.y; 203 int x = robot.x; 270 int x = robot.x; 204 assert( this[robot] == 'R' ); < 205 int lambda = 0; 271 int lambda = 0; 206 bool dead = false; < 207 if( '\\' == this[y+dy,x+dx] ) 272 if( '\\' == this[y+dy,x+dx] ) 208 lambda++; 273 lambda++; > 274 if( '!' == this[y+dy,x+dx] ) > 275 razor++; 209 if( " \\.O".count(this[y+dy,x+dx])==1 ) { | 276 if( " \\!.O".count(this[y+dy,x+dx])==1 ) { 210 this[y,x]=' '; 277 this[y,x]=' '; 211 this[y+dy,x+dx]='R'; 278 this[y+dy,x+dx]='R'; 212 robot = new Pos(y+dy,x+dx); 279 robot = new Pos(y+dy,x+dx); 213 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx 280 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx 214 this[y,x]=' '; 281 this[y,x]=' '; 215 this[y+dy,x+dx]='R'; 282 this[y+dy,x+dx]='R'; 216 this[y+dy*2,x+dx*2]='*'; 283 this[y+dy*2,x+dx*2]='*'; 217 robot = new Pos(y+dy,x+dx); 284 robot = new Pos(y+dy,x+dx); > 285 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { > 286 this[y,x]=' '; > 287 Pos tp = tr_target[this[y+dy,x+dx]]; > 288 foreach(p; tr_source[this[tp]]) > 289 this[p] = ' '; > 290 this[tp] = 'R'; > 291 robot = tp; 218 } 292 } 219 if( update() ) | 293 bool dead = update(turn); 220 dead = true; < 221 return tuple(lambda,dead); 294 return tuple(lambda,dead); 222 } 295 } 223 296 224 bool update() | 297 bool update(int turn) 225 { 298 { 226 bool dead = false; 299 bool dead = false; 227 300 228 char[][] next; 301 char[][] next; 229 foreach(y,s; data) 302 foreach(y,s; data) 230 next ~= s.dup; 303 next ~= s.dup; 231 304 ................................................................................................................................................................................ 259 dead=true; 332 dead=true; 260 } 333 } 261 } 334 } 262 else if(this[p]=='L') { 335 else if(this[p]=='L') { 263 if(!lambda) 336 if(!lambda) 264 access(p) = 'O'; 337 access(p) = 'O'; 265 } 338 } > 339 else if(this[p]=='W') { > 340 if( hige.is_growing_turn(turn) ) > 341 for(int dy=-1; dy<=+1; ++dy) > 342 for(int dx=-1; dx<=+1; ++dx) > 343 if(this[p.y+dy,p.x+dx] == ' ') > 344 access(new Pos(p.y+dy,p. > 345 } 266 } 346 } 267 data = next; 347 data = next; 268 return dead; 348 return dead; 269 } 349 } 270 } 350 } 271 351 272 //////////////////////////////////////////////////////////////////////////////// 352 //////////////////////////////////////////////////////////////////////////////// 273 353 274 class Game 354 class Game 275 { 355 { 276 mixin DeriveShow; | 356 public: 277 < 278 static Game load(File input) | 357 this(File input) 279 { 358 { 280 string[] raw_data; | 359 // Read map data 281 string[string] params; | 360 string[] map_data_lines; 282 < 283 // Raw map data; read until empty line. < 284 for(string line; !(line=input.readln().chomp()).empty; ) 361 for(string line; !(line=input.readln().chomp()).empty; ) 285 raw_data ~= line; | 362 map_data_lines ~= line; 286 | 363 287 // Additional commands; read until EOF. | 364 // H*W 288 for(string line; !(line=input.readln()).empty; ) { < 289 string[] ss = line.split(); < 290 if( ss.length == 2 ) | 365 H_ = map_data_lines.length; > 366 W_ = 0; > 367 foreach(mdl; map_data_lines) 291 params[ss[0]] = ss[1]; | 368 W_ = max(W_, mdl.length); 292 } | 369 293 < > 370 // Copy to modifiable buffer and adjust coordinates. 294 return load(raw_data, params); | 371 raw_data_ = new char[][H_+1]; 295 } < 296 < > 372 foreach(i,mdl; map_data_lines) { > 373 char[] buf = new char[mdl.length+1]; 297 static Game load(string[] raw_data, string[string] params) | 374 buf[0] = '#'; 298 { < > 375 buf[1..$] = mdl[]; 299 return new Game(raw_data, params); | 376 raw_data_[H_-i] = buf; 300 } | 377 } 301 | 378 302 this(string[] raw_data, string[string] params) | 379 // Detect objects > 380 for(int y=1; y<=H_; ++y) > 381 for(int x=1; x<raw_data_[y].length; ++x) 303 { | 382 { 304 this.map = Map.load(raw_data, params); < 305 this.water = Water.load(params); < 306 } < > 383 char c = raw_data_[y][x]; > 384 switch(c) 307 | 385 { 308 Game clone() const { return new Game(this); } < 309 this(const(Game) g) { | 386 case '#': 310 map = g.map.clone(); | 387 case '.': 311 water = g.water.clone(); | 388 case ' ': 312 turn = g.turn; | 389 break; 313 dead = g.dead; | 390 case 'L': 314 lambda = g.lambda; | 391 case 'O': 315 exit_bonus = g.exit_bonus; | 392 lift_pos_ = new Pos(y,x); 316 under_water = g.under_water; | 393 break; > 394 case 'A': .. case 'I': > 395 case '1': .. case '9': > 396 trampoline_pos_[c] = new Pos(y,x); > 397 break; > 398 case '!': > 399 razor_pos_ ~= new Pos(y,x); > 400 break; > 401 case '\\': > 402 lambda_pos_ ~= new Pos(y,x); > 403 break; 317 } | 404 > 405 // Moving objects are erased from raw_data_ > 406 case 'R': > 407 robot_pos_ = new Pos(y,x); > 408 raw_data_[y][x] = ' '; > 409 break; > 410 case '*': > 411 case 'W': > 412 dynamic_objects_[new Pos(y,x)] = c; > 413 raw_data_[y][x] = ' '; > 414 if(c=='*') > 415 may_update_[new Pos(y,x)] = true; > 416 break; > 417 default: > 418 assert(false); 318 | 419 } 319 void command(char c) < 320 { < 321 if(dead || cleared) < 322 return; < 323 | 420 } 324 if(c == 'A') < > 421 > 422 // Read other parameters > 423 for(string line; !(line=input.readln()).empty; ) 325 { 424 { 326 exit_bonus = 1; | 425 string[] ss = line.split(); 327 return; | 426 if( ss.length == 2 ) 328 } < > 427 switch(ss[0]) 329 | 428 { 330 // TODO: clarify the event order | 429 case "Water": water_base_ = ss[1].to!int(); 331 Tuple!(int,bool) ld = map.command(c); | 430 case "Flooding": water_pace_ = ss[1].to!int(); 332 if( map.cleared() ) { | 431 case "Waterproof": max_air_ = ss[1].to!int(); 333 exit_bonus = 2; | 432 case "Growth": hige_pace_ = ss[1].to!int(); > 433 case "Razors": num_razor_ = ss[1].to!int(); > 434 default: assert(false); 334 } | 435 } 335 else { < 336 lambda += ld[0]; < 337 if( ld[1] ) { | 436 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar 338 dead = true; < > 437 { > 438 char fr=ss[1][0], to=ss[3][0]; > 439 trampoline_[fr] = to; > 440 if(to !in trampoline_rev_) trampoline_rev_[to] = > 441 trampoline_rev_[to] ~= fr; 339 } 442 } 340 } 443 } 341 if( map.robot.y <= water_level ) < > 444 342 ++under_water; | 445 air_left_ = max_air_; 343 else < 344 under_water = 0; < 345 if( under_water > map.waterproof ) < 346 dead = true; < 347 turn += 1; < 348 } 446 } 349 447 350 Map map; < 351 Water water; < 352 int turn = 0; < 353 bool dead = false; < 354 int lambda = 0; < 355 int exit_bonus = 0; < 356 int under_water = 0; < 357 // TODO: when adding members, take care of clone(). < 358 // TODO: fix this poor design. < 359 < 360 @property const { 448 @property const { 361 long score() { return lambda*25L*(1+exit_bonus) - turn; } | 449 int H() { return H_; } > 450 int W() { return W_; } > 451 char trampoline(char c) { return (c in trampoline_ ? trampoline_ > 452 const(Pos)[] trampoline_rev(char c) { > 453 const(Pos)[] pp; > 454 if(c in trampoline_rev_) { > 455 foreach(ch; trampoline_rev_[c]) > 456 pp ~= trampoline_pos_[ch]; > 457 } > 458 return pp; > 459 } 362 int water_level() { return water.level(turn); } | 460 int water_level() { > 461 return water_pace_ ? water_base_ + turn_/water_pace_ : w > 462 } 363 int water_until_rise() { return water.until_rise(turn); } | 463 int water_until_rise() { > 464 return water_pace_ ? water_pace_ - turn_%water_pace_ : i > 465 } > 466 int hige_until_rise() { > 467 return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int. > 468 } > 469 bool is_hige_turn() { > 470 return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : f > 471 } > 472 int hp() { return air_left_; } > 473 int num_razor() { return num_razor_; } 364 bool cleared() { return exit_bonus>0; } | 474 bool cleared() { return cleared_; } 365 int hp() { return map.waterproof - under_water; } < 366 long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus < > 475 bool dead() { return dead_; } > 476 long score() { return num_lambda_*(dead_ ? 25L : cleared_ ? 75L > 477 const(Pos) robot() { return robot_pos_; } > 478 const(Pos) lift() { return lift_pos_; } > 479 Pos[] lambdas() { > 480 Pos[] pp; > 481 foreach(p; lambda_pos_) > 482 pp ~= p.clone(); > 483 return pp; > 484 } > 485 Pos[] razors() { > 486 Pos[] pp; > 487 foreach(p; razor_pos_) > 488 pp ~= p.clone(); > 489 return pp; > 490 } > 491 const(Pos)[] higes() { > 492 const(Pos)[] pp; > 493 foreach(p,c; dynamic_objects_) > 494 if(c=='W') > 495 pp ~= p; > 496 return pp; > 497 } > 498 } > 499 const { > 500 char opIndex(in Pos p) { return opIndex(p.y, p.x); } > 501 char opIndex(int y, int x) { return map_get(y, x); } > 502 } > 503 > 504 public: > 505 void command(char c) > 506 { > 507 if(dead || cleared) > 508 return; > 509 > 510 if(c == 'U') command_move(+1, 0); > 511 if(c == 'D') command_move(-1, 0); > 512 if(c == 'L') command_move(0, -1); > 513 if(c == 'R') command_move(0, +1); > 514 if(c == 'S') use_razor(); > 515 if(c == 'W') {} > 516 > 517 if(!cleared) > 518 { > 519 map_update(); > 520 water_update(); > 521 } > 522 turn_ ++; > 523 } > 524 > 525 void command_move(int dy, int dx) > 526 { > 527 int y = robot_pos_.y, x = robot_pos_.x; > 528 char c = this[y+dy, x+dx]; > 529 Pos p = new Pos(y+dy, x+dx); > 530 > 531 switch(c){ > 532 case 'O': > 533 cleared_ = true; > 534 move_robot_to(p); > 535 break; > 536 case '\\': > 537 take_lambda_at(p); > 538 move_robot_to(p); > 539 break; > 540 case '!': > 541 take_razor_at(p); > 542 move_robot_to(p); > 543 break; > 544 case 'A': .. case 'I': > 545 enter_trampoline_at(p, c); > 546 break; > 547 case ' ': > 548 case '.': > 549 move_robot_to(p); > 550 break; > 551 case '*': > 552 if(dy!=0 || this[y,x+dx*2]!=' ') > 553 break; > 554 move_robot_to(p); > 555 push_rock(p, new Pos(y,x+dx*2)); > 556 break; > 557 default: > 558 break; > 559 } > 560 } > 561 > 562 void use_razor() > 563 { > 564 if(num_razor_ == 0) > 565 return; > 566 num_razor_ --; > 567 > 568 for(int dy=-1; dy<=+1; ++dy) > 569 for(int dx=-1; dx<=+1; ++dx) if(dy||dx) > 570 { > 571 Pos p = new Pos(robot_pos_.y+dy, robot_pos_.x+dx); > 572 if(auto it = p in dynamic_objects_) > 573 if(*it == 'W') { > 574 something_gone(p); > 575 dynamic_objects_.remove(p); > 576 } > 577 } > 578 } > 579 > 580 void take_lambda_at(Pos p) > 581 { > 582 map_set_empty(p); > 583 num_lambda_ ++; > 584 lambda_pos_ = lambda_pos_.erase(p); > 585 } > 586 > 587 void take_razor_at(Pos p) > 588 { > 589 map_set_empty(p); > 590 num_razor_ ++; > 591 razor_pos_ = razor_pos_.erase(p); > 592 } > 593 > 594 void enter_trampoline_at(Pos p, char c) > 595 { > 596 char d = trampoline(c); > 597 foreach(cc; trampoline_rev_[d]) { > 598 Pos pp = trampoline_pos_[cc]; > 599 something_gone(pp); > 600 map_set_empty(pp); > 601 } > 602 move_robot_to(trampoline_pos_[d]); > 603 } > 604 > 605 void move_robot_to(Pos p) > 606 { > 607 something_gone(robot_pos_); > 608 map_set_empty(p.y, p.x); > 609 robot_pos_ = p; > 610 } > 611 > 612 void push_rock(Pos fr, Pos to) > 613 { > 614 dynamic_objects_.remove(fr); > 615 dynamic_objects_[to] = '*'; > 616 may_update_[to] = true; > 617 } > 618 > 619 void something_gone(Pos p) > 620 { > 621 for(int dy=0; dy<=+1; ++dy) > 622 for(int dx=-1; dx<=+1; ++dx) if(dy||dx) > 623 may_update_[new Pos(p.y+dy,p.x+dx)] = true; > 624 } > 625 > 626 void map_update() > 627 { > 628 Pos[] may_update_list; > 629 foreach(p,_; may_update_) > 630 if(this[p] == '*') > 631 may_update_list ~= p; > 632 may_update_ = null; > 633 > 634 if( is_hige_turn() ) > 635 foreach(p,c; dynamic_objects_) > 636 if(c == 'W') > 637 may_update_list ~= p; > 638 > 639 sort(may_update_list); > 640 char[Pos] to_be_written; > 641 foreach(p; may_update_list) > 642 if(is_hige_turn() && this[p]=='W') > 643 { > 644 for(int dy=-1; dy<=+1; ++dy) > 645 for(int dx=-1; dx<=+1; ++dx) { > 646 Pos q = new Pos(p.y+dy,p.x+dx); > 647 if( this[q] == ' ' ) > 648 to_be_written[q] = 'W'; > 649 } > 650 } > 651 else > 652 { > 653 int y = p.y; > 654 int x = p.x; > 655 char below = this[y-1,x]; > 656 // * > 657 // _ > 658 if(below==' ') { > 659 Pos q = new Pos(y-1,x); > 660 to_be_written[p] = ' '; > 661 to_be_written[q] = '*'; > 662 may_update_[q] = true; > 663 } > 664 // *_ *_ > 665 // *_ or \_ > 666 else if((below=='*'||below=='\\')&&this[y-1,x+1] > 667 Pos q = new Pos(y-1,x+1); > 668 to_be_written[p] = ' '; > 669 to_be_written[q] = '*'; > 670 may_update_[q] = true; > 671 } > 672 // _* > 673 // _* > 674 else if(below=='*'&&this[y-1,x-1]==' '&&this[y,x > 675 Pos q = new Pos(y-1,x-1); > 676 to_be_written[p] = ' '; > 677 to_be_written[q] = '*'; > 678 may_update_[q] = true; > 679 } > 680 } > 681 > 682 foreach(p,c; to_be_written) { > 683 dynamic_objects_[p] = c; > 684 if(c=='*' && p.y==robot_pos_.y+1 && p.x==robot_pos_.x) > 685 dead_ = true; > 686 } > 687 > 688 if(lambda_pos_.empty) > 689 raw_data_[lift_pos_.y][lift_pos_.x] = 'O'; > 690 } > 691 > 692 void water_update() > 693 { > 694 if( robot_pos_.y <= water_level() ) > 695 air_left_ --; > 696 else > 697 air_left_ = max_air_; > 698 if( air_left_ < 0 ) > 699 dead_ = true; > 700 } > 701 > 702 private: > 703 char map_get(int y, int x) const > 704 { > 705 if( y<1 || H<y || x<1 || W<x ) return '#'; > 706 Pos p = new Pos(y,x); > 707 if(p == robot_pos_) > 708 return 'R'; > 709 if(auto it = (p in dynamic_objects_)) > 710 return *it; > 711 if( x<0 || raw_data_[y].length<=x ) return ' '; > 712 return raw_data_[y][x]; > 713 } > 714 > 715 void map_set_empty(in Pos p) > 716 { > 717 return map_set_empty(p.y, p.x); > 718 } > 719 > 720 void map_set_empty(int y, int x) > 721 { > 722 if( y<1 || H<y || x<1 || W<x ) return; > 723 if( x<0 || raw_data_[y].length<=x ) return; > 724 raw_data_[y][x] = ' '; > 725 } > 726 > 727 public: > 728 Game clone() const { return new Game(this); } > 729 this(in Game g) { > 730 H_ = g.H_; > 731 W_ = g.W_; > 732 raw_data_ = new char[][g.raw_data_.length]; > 733 foreach(i,d; g.raw_data_) raw_data_[i] = d.dup; > 734 trampoline_pos_ = cast(Pos[char]) g.trampoline_pos_; > 735 razor_pos_ = (cast(Game)g).razor_pos_.dup; > 736 lambda_pos_ = (cast(Game)g).lambda_pos_.dup; > 737 lift_pos_ = g.lift_pos_.clone(); > 738 robot_pos_ = g.robot_pos_.clone(); > 739 dynamic_objects_ = dup(g.dynamic_objects_); > 740 trampoline_ = (cast(Game)g).trampoline_; > 741 trampoline_rev_ = (cast(Game)g).trampoline_rev_; > 742 water_base_ = g.water_base_; > 743 water_pace_ = g.water_pace_; > 744 max_air_ = g.max_air_; > 745 hige_pace_ = g.hige_pace_; > 746 num_razor_ = g.num_razor_; > 747 num_lambda_ = g.num_lambda_; > 748 turn_ = g.turn_; > 749 air_left_ = g.air_left_; > 750 cleared_ = g.cleared_; > 751 dead_ = g.dead_; > 752 may_update_ = dup(g.may_update_); > 753 } > 754 > 755 V[K] dup(V,K)(in V[K] aa) { > 756 V[K] aa2; > 757 foreach(k,v; aa) aa2[k] = v; > 758 return aa2; 367 } 759 } 368 } | 760 > 761 private: > 762 int H_; > 763 int W_; > 764 char[][] raw_data_; > 765 Pos[char] trampoline_pos_; > 766 Pos[] razor_pos_; > 767 Pos[] lambda_pos_; > 768 Pos lift_pos_; > 769 Pos robot_pos_; > 770 char[Pos] dynamic_objects_; > 771 char[char] trampoline_; > 772 char[][char] trampoline_rev_; > 773 int water_base_ = 0; > 774 int water_pace_ = 0; > 775 int max_air_ = 10; > 776 int hige_pace_ = 25; > 777 int num_razor_ = 0; > 778 int num_lambda_ = 0; 369 779 370 unittest | 780 int turn_ = 0; 371 { < > 781 int air_left_ = 0; 372 Game.load(["###","...","#RL"], ["xxx":"yyy"]); | 782 bool cleared_ = false; > 783 bool dead_ = false; > 784 bool[Pos] may_update_; 373 } 785 }

Modified src/gui.d from [e76b6b97ba56256b] to [e84cacd6262f93a7].

1 import dfl.all; 1 import dfl.all; 2 import util; 2 import util; 3 import game; 3 import game; 4 import output; < 5 import driver; 4 import driver; 6 //import solver; < 7 pragma(lib, "dfl.lib"); < 8 5 9 class GUI : Form, GameObserver | 6 class GUI(Solver) : Form, GameObserver 10 { 7 { 11 bool on_game_changed(char c, const(Game) g, bool finished) { | 8 this(in Game g) > 9 { > 10 this.solver = new Solver(g); > 11 setup_size(g.W, g.H); > 12 setup_resources(g); 12 draw(gr, g); | 13 draw(g); 13 invalidate(); < 14 return false; < > 14 } > 15 > 16 private void delegate(char c) fn; > 17 void set_fn(F)(F f) { this.fn = f; } > 18 > 19 void run(bool automate = false) > 20 { > 21 if(automate) { > 22 Timer t = new Timer; > 23 t.interval = 50; > 24 t.tick ~= (Timer sender, EventArgs ea){ > 25 fn(solver.single_step()); > 26 }; > 27 t.start(); > 28 this.closing ~= (Form f,CancelEventArgs c){t.stop();}; > 29 } else { > 30 setup_keyhandling(); > 31 } > 32 Application.run(this); 15 } 33 } 16 34 17 private { | 35 override void on_game_changed(char c, in Game g, bool finished) 18 int cell; < 19 int turn = 0; < 20 | 36 { 21 Font font; < 22 Color[char] colors; < 23 string[char] render; < 24 void delegate(char c) fn; < > 37 draw(g); 25 } 38 } 26 39 27 this(const(Game) g) | 40 private: > 41 int cell; > 42 > 43 void setup_size(int W, int H) 28 { 44 { 29 noMessageFilter(); < 30 this.setStyle(ControlStyles.OPAQUE, true); < 31 this.fn = fn; < 32 < 33 this.paint ~= &my_paint; < 34 this.keyDown ~= &my_keydown; < 35 < 36 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; 45 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; 37 this.maximizeBox = false; 46 this.maximizeBox = false; 38 this.minimizeBox = false; 47 this.minimizeBox = false; 39 this.cell = min(1024/g.map.W, 640/g.map.H); | 48 this.cell = min(1024/W, 640/H); 40 this.clientSize = Size(g.map.W*cell, g.map.H*cell); | 49 this.clientSize = Size(W*cell, H*cell); > 50 } 41 51 42 const scrH = this.clientSize.height; | 52 Font font; 43 const scrW = this.clientSize.width; | 53 Color[char] colors; 44 this.gr = new MemoryGraphics(scrW, scrH); | 54 string[char] render; > 55 Graphics graphicContext; 45 56 46 // Resources | 57 void setup_resources(in Game g) > 58 { > 59 this.graphicContext = new MemoryGraphics(this.clientSize.width, > 60 this.setStyle(ControlStyles.OPAQUE, true); 47 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); 61 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); 48 this.backColor = Color(255,255,255); 62 this.backColor = Color(255,255,255); 49 this.colors['#'] = 63 this.colors['#'] = 50 this.colors['.'] = Color(255,191,127); 64 this.colors['.'] = Color(255,191,127); 51 this.colors['*'] = Color(255,127,127); 65 this.colors['*'] = Color(255,127,127); 52 this.colors['R'] = Color(128,128,0); 66 this.colors['R'] = Color(128,128,0); 53 this.colors['D'] = Color(255,0,0); // Dead | 67 this.colors['d'] = Color(255,0,0); 54 this.colors['\\'] = 68 this.colors['\\'] = 55 this.colors['L'] = 69 this.colors['L'] = 56 this.colors['O'] = Color(127,255,127); 70 this.colors['O'] = Color(127,255,127); 57 this.colors['W'] = Color(204,229,255); // water | 71 this.colors['w'] = Color(204,229,255); 58 < > 72 this.colors['W'] = > 73 this.colors['!'] = Color(159,159,159); > 74 foreach(char c; 'A'..'J') this.colors[c] = Color(142,142,255); > 75 foreach(char c; '1'..':') this.colors[c] = Color(255,142,255); 59 this.render['#'] = "■"; 76 this.render['#'] = "■"; 60 this.render['*'] = "✹"; 77 this.render['*'] = "✹"; 61 this.render['.'] = "♒"; 78 this.render['.'] = "♒"; 62 this.render['\\'] = "λ"; 79 this.render['\\'] = "λ"; 63 this.render['R'] = "☃"; 80 this.render['R'] = "☃"; 64 this.render['D'] = "☠"; | 81 this.render['d'] = "☠"; 65 this.render['L'] = "☒"; 82 this.render['L'] = "☒"; 66 this.render['O'] = "☐"; 83 this.render['O'] = "☐"; 67 draw(gr, g); | 84 this.render['W'] = "ꔣ"; > 85 this.render['!'] = "✄"; > 86 foreach(char c; 'A'..'J') this.render[c] = [cast(dchar)('☢'+g.tr > 87 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1 > 88 this.paint ~= (Control c, PaintEventArgs ev) { > 89 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientS 68 } | 90 }; 69 < 70 void set_fn(F)(F f) { this.fn = f; } < 71 < 72 void run() { < 73 Application.run(this); < 74 } 91 } 75 92 76 private: < 77 Graphics gr; < 78 < 79 void my_paint(Control, PaintEventArgs ev) < 80 { < 81 gr.copyTo(ev.graphics, Rect(0,0,this.clientSize.width,this.clien < 82 } < 83 < 84 void draw(Graphics gr, const(Game) g) | 93 void draw(in Game g) 85 { 94 { 86 int scrW = this.clientSize.width; 95 int scrW = this.clientSize.width; 87 int scrH = this.clientSize.height; 96 int scrH = this.clientSize.height; > 97 88 // Fill bg. 98 // Fill bg. 89 gr.fillRectangle(this.backColor, Rect(0,0,scrW,scrH)); | 99 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH) 90 100 91 // Fill water. 101 // Fill water. 92 int w = g.water_level(); 102 int w = g.water_level(); 93 gr.fillRectangle(this.colors['W'], Rect(0, scrH-cell*w-1, scrW, | 103 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell 94 104 95 // Paint map. 105 // Paint map. 96 for(int y=1; y<=g.map.H; ++y) | 106 for(int y=1; y<=g.H; ++y) 97 for(int x=1; x<=g.map.W; ++x) { | 107 for(int x=1; x<=g.W; ++x) { 98 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 108 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 99 char c = g.map[y,x]; | 109 char c = g[y,x]; 100 if( c != ' ' ) { 110 if( c != ' ' ) { 101 if( c == 'R' && g.dead ) 111 if( c == 'R' && g.dead ) 102 c = 'D'; | 112 c = 'd'; 103 gr.drawText(this.render[c], font, this.colors[c] | 113 graphicContext.drawText(this.render[c], font, th 104 } 114 } 105 } 115 } 106 116 107 set_text(g); | 117 // Update textual info. > 118 this.text = .text( > 119 "Score: ", g.score, > 120 " Air: ", g.hp, > 121 " Tide: ", g.water_until_rise, > 122 " Wadler: ", g.hige_until_rise, > 123 " Razor: ", g.num_razor); > 124 invalidate(); > 125 } > 126 > 127 private: > 128 void setup_keyhandling() > 129 { > 130 noMessageFilter(); > 131 this.keyDown ~= &my_keydown; > 132 } > 133 > 134 void do_manual_command(char c) > 135 { > 136 solver.force(c); > 137 fn(c); 108 } 138 } 109 139 110 void my_keydown(Control c, KeyEventArgs ev) 140 void my_keydown(Control c, KeyEventArgs ev) 111 { 141 { 112 switch(ev.keyCode) 142 switch(ev.keyCode) 113 { 143 { 114 case Keys.DOWN: fn('D'); break; | 144 case Keys.DOWN: do_manual_command('D'); break; 115 case Keys.UP: fn('U'); break; | 145 case Keys.UP: do_manual_command('U'); break; 116 case Keys.LEFT: fn('L'); break; | 146 case Keys.LEFT: do_manual_command('L'); break; 117 case Keys.RIGHT: fn('R'); break; | 147 case Keys.RIGHT: do_manual_command('R'); break; 118 case Keys.W: fn('W'); break; | 148 case Keys.W: do_manual_command('W'); break; > 149 case Keys.S: do_manual_command('S'); break; 119 case Keys.A: fn('A'); break; | 150 case Keys.A: do_manual_command('A'); break; > 151 case Keys.G: fn(solver.single_step()); break; 120 default: break; 152 default: break; 121 } 153 } 122 } 154 } 123 155 124 void set_text(const(Game) g) { | 156 Solver solver; 125 this.text = .text("Score: ", g.score, " Air: ", g.hp, " Tide: ", < 126 } < 127 } < 128 < 129 void main(string[] args) < 130 { < 131 auto d = new Driver(File(args[1])); < 132 d.addObserver!(GuardedOutput)(); < 133 GUI g = d.addObserver!(GUI)(); < 134 g.set_fn(&d.command); < 135 g.run(); < 136 } 157 }

Added src/gui_main.d version [05082d0f328d756c]

> 1 import gui; > 2 import output; > 3 import driver; > 4 import solver; > 5 import std.stdio; > 6 pragma(lib, "dfl.lib"); > 7 > 8 void main(string[] args) > 9 { > 10 Driver d = new Driver(stdin); > 11 d.addObserver!(GuardedOutput)(); > 12 auto g = d.addObserver!(GUI!MainSolver)(); > 13 g.set_fn(&d.command); > 14 g.run(); > 15 }

Modified src/output.d from [2ca374354297c908] to [e2d0d7db868c3a44].

1 import util; 1 import util; 2 import game; 2 import game; 3 import driver; 3 import driver; 4 import std.c.stdlib; < 5 import core.stdc.signal; 4 import core.stdc.signal; 6 5 7 class NilOutput : GameObserver 6 class NilOutput : GameObserver 8 { 7 { 9 this(const(Game) g) {} | 8 this(in Game g) {} 10 override bool on_game_changed(char c, const(Game) g, bool finished) {ret | 9 override void on_game_changed(char c, in Game g, bool finished) {} 11 } 10 } 12 11 13 class StdOutput : GameObserver 12 class StdOutput : GameObserver 14 { 13 { 15 this(const(Game) g) {} | 14 this(in Game g) {} 16 override bool on_game_changed(char c, const(Game) g, bool finished) | 15 override void on_game_changed(char c, in Game g, bool finished) 17 { 16 { 18 stdout.write(c); 17 stdout.write(c); 19 stdout.flush(); 18 stdout.flush(); 20 return false; < 21 } 19 } 22 } 20 } 23 21 24 class GuardedOutput : GameObserver 22 class GuardedOutput : GameObserver 25 { 23 { 26 this(const(Game) g) | 24 this(in Game g) 27 { 25 { 28 setup_sigint_handling(); 26 setup_sigint_handling(); 29 ideal_log ~= g.score_if_abort_now; | 27 score_log ~= g.score; > 28 flushed = false; 30 } 29 } 31 30 32 override bool on_game_changed(char c, const(Game) g, bool finished) | 31 override void on_game_changed(char c, in Game g, bool finished) 33 { 32 { > 33 if(flushed) > 34 return; > 35 34 log ~= c; 36 log ~= c; 35 score_log ~= g.score; 37 score_log ~= g.score; 36 ideal_log ~= g.score_if_abort_now; < 37 if(finished) | 38 if(finished || log.length+1==g.W*g.H) 38 flush(); 39 flush(); 39 return false; < 40 } 40 } 41 41 42 private: 42 private: 43 string log; 43 string log; 44 long[] score_log; 44 long[] score_log; 45 long[] ideal_log; | 45 bool flushed; 46 46 47 void flush() 47 void flush() 48 { 48 { > 49 if(flushed) > 50 return; > 51 49 Tuple!(long, int, int) cand; | 52 Tuple!(long, int) cand; 50 cand[0] = long.min; 53 cand[0] = long.min; 51 54 52 for(int i=0; i<score_log.length; ++i) 55 for(int i=0; i<score_log.length; ++i) 53 if(cand[0] < score_log[i]) 56 if(cand[0] < score_log[i]) 54 cand = tuple(score_log[i],i,0); | 57 cand = tuple(score_log[i],i); 55 for(int i=0; i<ideal_log.length; ++i) < 56 if(cand[0] < ideal_log[i]) < 57 cand = tuple(ideal_log[i],i,1); < 58 58 59 if(cand[2]==0) { < 60 string str = log[0..cand[1]+1]; < 61 std.c.stdio.printf("%.*s\n", str.length, str.ptr); < 62 } else { < 63 string str = log[0..cand[1]]; < 64 std.c.stdio.printf("%.*sA\n", str.length, str.ptr); | 59 std.c.stdio.printf("%.*sA\n", cand[1], log.ptr); 65 } < 66 std.c.stdio.fflush(std.c.stdio.stdout); 60 std.c.stdio.fflush(std.c.stdio.stdout); > 61 flushed = true; 67 } 62 } 68 63 69 private: 64 private: 70 static __gshared GuardedOutput g_output; 65 static __gshared GuardedOutput g_output; 71 66 72 void setup_sigint_handling() 67 void setup_sigint_handling() 73 { 68 { 74 assert(g_output is null); 69 assert(g_output is null); 75 g_output = this; 70 g_output = this; 76 extern(C) static void catch_sigint(int) { g_output.flush(); appl 71 extern(C) static void catch_sigint(int) { g_output.flush(); appl 77 core.stdc.signal.signal(SIGINT, &catch_sigint); 72 core.stdc.signal.signal(SIGINT, &catch_sigint); 78 } 73 } 79 } 74 }

Modified src/solver.d from [42db89cb5c63a7bd] to [22c356ff1975e92f].

1 import util; 1 import util; 2 import game; 2 import game; 3 import output; < 4 3 5 int g_wc = 0; | 4 class Solver_0 > 5 { > 6 this(in Game g) {} > 7 char single_step() { return 'W'; } > 8 void force(char c) {} > 9 } 6 10 7 void act(Game g) | 11 class Solver_1 8 { 12 { > 13 int wait_count = 0; > 14 int choke_count = 0; > 15 > 16 Game g; > 17 this(in Game g) > 18 { > 19 this.g = g.clone(); > 20 forbidden_cell = new bool[][](g.H+2, g.W+2); > 21 } > 22 > 23 char single_step() > 24 { > 25 Tuple!(string,int) de = death_move(g); > 26 char c = act(g, de[0], de[1]); > 27 force(c); > 28 return c; > 29 } > 30 > 31 void force(char c) > 32 { > 33 if(c != 'A') > 34 g.command(c); > 35 } > 36 > 37 Tuple!(string,int) death_move(const(Game) g) > 38 { > 39 string death; > 40 int choice = 0; > 41 foreach(char c; "UDLRW") { > 42 Game gg = g.clone(); > 43 gg.command(c); > 44 if( !gg.cleared && gg.dead ) > 45 death ~= c; > 46 else if( gg.robot != g.robot ) > 47 choice++; > 48 else if( c != 'W' ) // meaningless move > 49 death ~= c; > 50 } > 51 return tuple(death, choice); > 52 } > 53 > 54 Tuple!(Pos, int)[] log; > 55 bool[][] forbidden_cell; > 56 > 57 char act(const(Game) g, string death, int breath) > 58 { 9 Pos ro = g.map.robot; | 59 const Pos ro = g.robot; > 60 const Pos li = g.lift; 10 Pos[] la = g.map.lambdas(); | 61 Pos[] la = g.lambdas(); 11 Pos li = g.map.lift; < > 62 sort!((Pos a,Pos b){ > 63 int ad=abs(a.y-li.y)+abs(a.x-li.x); > 64 int bd=abs(b.y-li.y)+abs(b.x-li.x); > 65 return ad>bd;; > 66 })(la); > 67 Pos[] ra = g.razors(); > 68 const(Pos)[] hi = g.higes(); 12 | 69 13 char c = 'W'; < 14 if( la.empty ) { < 15 auto r = search(g, ro, li); < 16 c = r[0]; < 17 } else { < 18 Tuple!(char,int)[] cand; 70 Tuple!(char,int)[] cand; 19 foreach(lam; la) | 71 char c = 'W'; > 72 if( la.empty ) { > 73 cand = search(g, ro, [li], death); > 74 } else { 20 cand ~= search(g, ro, lam); | 75 cand ~= search(g, ro, la~ra, death); > 76 } > 77 > 78 // 'higesori' mode > 79 if( !hi.empty && g.num_razor>0 ) { > 80 int his = 0; > 81 for(int dy=-1; dy<=+1; ++dy) > 82 for(int dx=-1; dx<=+1; ++dx) > 83 if(g[ro.y+dy,ro.x+dx] == 'W') > 84 his++; > 85 > 86 if(his>=2 || his==hi.length) > 87 cand = [tuple('S',int.max)]; > 88 if(cand.empty) { > 89 const(Pos)[] tgt; > 90 for(int y=1; y<=g.H; ++y) > 91 for(int x=1; x<=g.W; ++x) > 92 if(g[y,x]=='.'||g[y,x]==' ') { > 93 his = 0; > 94 for(int dy=-1; dy<=+1; ++dy) > 95 for(int dx=-1; dx<=+1; ++dx) > 96 if(g[y+dy,x+dx] == 'W') > 97 his++; > 98 if(his>=2) > 99 tgt ~= new Pos(y,x); > 100 } > 101 cand ~= search(g, ro, tgt, death, true); > 102 } > 103 } > 104 > 105 // 'dig' mode > 106 if(cand.empty) { > 107 const(Pos)[] tgt; > 108 for(int y=1; y<=g.H; ++y) > 109 for(int x=1; x<=g.W; ++x) > 110 if(g[y,x]=='.') > 111 if(g[y+1,x]=='*'||g[y+1,x-1]=='*'||g[y+1 > 112 ||g[y,x+1]=='*'||g[y,x-1]=='*') > 113 tgt ~= new Pos(y,x); > 114 cand ~= search(g, ro, tgt, death, true); > 115 } > 116 > 117 if(cand.empty) { > 118 choke_count++; > 119 cand ~= tuple('W',int.max); > 120 } 21 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ 121 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ 22 if(c1[1] != c2[1]) 122 if(c1[1] != c2[1]) 23 return c1[1] < c2[1]; 123 return c1[1] < c2[1]; 24 return c1[0] < c2[0]; 124 return c1[0] < c2[0]; 25 })(cand); 125 })(cand); 26 c = cand[0][0]; 126 c = cand[0][0]; 27 } | 127 28 if(c=='W') { | 128 if(death.count(c) || wait_count>=2) { 29 g_wc++; | 129 foreach(char live; "UDLRW") 30 if(g_wc > 10) | 130 if(death.count(live)==0) { > 131 c=live; > 132 break; > 133 } > 134 } > 135 > 136 if(c == 'W') > 137 wait_count++; > 138 else > 139 wait_count = 0; > 140 if(choke_count >= g.H) 31 c = 'A'; 141 c = 'A'; 32 } | 142 33 else | 143 bool[char] choice; > 144 foreach(t; cand) > 145 choice[t[0]] = true; > 146 log ~= tuple(ro.clone(), cast(int)choice.length); > 147 if(log.length > 5) > 148 log = log[$-5..$]; 34 g_wc = 0; | 149 int cnt = 0; 35 g.command(c); < 36 } < 37 < 38 Tuple!(char,int) search(Game g, Pos s, Pos o) < 39 { < 40 Pos[] q = [o]; < 41 bool[][] v = new bool[][](g.map.H+2, g.map.W+2); < 42 for(int step=1; q.length; ++step) { < 43 Pos[] q2; < 44 foreach(p; q) { | 150 foreach(l; log) 45 int[] dy=[-1,+1,0,0]; < 46 int[] dx=[0,0,-1,+1]; < 47 for(int i=0; i<4; ++i) { < 48 int y = p.y+dy[i]; < 49 int x = p.x+dx[i]; < 50 if(v[y][x]) continue; < 51 if(y==s.y && x==s.x) { < 52 if(i==0) return tuple('U',step); < 53 if(i==1) return tuple('D',step); < 54 if(i==2) return tuple('R',step); < 55 if(i==3) return tuple('L',step); < 56 } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { < 57 q2 ~= new Pos(y,x); < 58 v[y][x]=true; < 59 } else if(g.map[y,x]=='.' && g.map[y-1,x]!='*') < 60 q2 ~= new Pos(y,x); < 61 v[y][x]=true; < 62 } < 63 } < > 151 if(l[0] == log[$-1][0]) > 152 ++cnt; > 153 if( cnt >= 3 && breath==1 ) { > 154 forbidden_cell[ro.y][ro.x] = true; 64 } 155 } 65 q = q2; < > 156 > 157 return c; 66 } 158 } > 159 > 160 Tuple!(char,int)[] search(in Game g, in Pos s, in Pos[] gs, string death > 161 { > 162 bool danger(int y, int x) > 163 { > 164 if(g[y,x] == ' ' || g[y,x] == 'R') > 165 return false; > 166 if(g[y+1,x] == '*') > 167 return true; > 168 if(g[y+1,x-1]=='*' && (g[y,x-1]=='\\'||g[y,x-1]=='*') && > 169 return true; > 170 if(g[y+1,x+1]=='*' && (g[y,x+1]=='*') && (g[y+1,x]==' '| > 171 return true; > 172 if(g[y,x-1]=='*' && (g[y-1,x-1]=='\\'||g[y-1,x-1]=='*') > 173 return true; > 174 if(g[y,x+1]=='*' && (g[y-1,x+1]=='*') && (g[y-1,x]==' '| > 175 return true; > 176 return false; > 177 } > 178 > 179 // avoid directly below '*' > 180 Tuple!(char,int)[] tryA() { > 181 const(Pos)[] q; > 182 foreach(p; gs) > 183 if(!danger(p.y,p.x)) > 184 q ~= p; > 185 bool[][] v = new bool[][](g.H+2, g.W+2); > 186 foreach(p; q) v[p.y][p.x]=true; > 187 for(int step=1; q.length; ++step) { > 188 Pos[] q2; > 189 foreach(p; q) { > 190 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; > 191 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; > 192 for(int i=0; i<yyy.length; ++i) { > 193 int y = yyy[i]; > 194 int x = xxx[i]; > 195 if('1'<=g[y,x]&&g[y,x]<='9') { > 196 foreach(ppp; g.trampolin > 197 yyy ~= ppp.y; > 198 xxx ~= ppp.x; > 199 } > 200 continue; > 201 } > 202 if(v[y][x]) continue; > 203 if(y==s.y && x==s.x && i<4) { > 204 char c = "UDRL"[i]; > 205 if( death.count(c) == 0 > 206 return [tuple(c, > 207 } else if(forbidden_cell[y][x]){ > 208 } else if(g[y,x]==' '||g[y,x]==' > 209 if(danger(y,x)) > 210 continue; > 211 q2 ~= new Pos(y,x); > 212 v[y][x]=true; > 213 } > 214 } > 215 } 67 q = [o]; | 216 q = q2; > 217 } > 218 return []; > 219 } > 220 > 221 // any empty space is my ground > 222 Tuple!(char,int)[] tryB() { > 223 const(Pos)[] q; > 224 foreach(p; gs) q ~= p; 68 v = new bool[][](g.map.H+2, g.map.W+2); | 225 bool[][] v = new bool[][](g.H+2, g.W+2); > 226 foreach(p; q) v[p.y][p.x]=true; 69 for(int step=1000; q.length; ++step) { | 227 for(int step=10; q.length; ++step) { 70 Pos[] q2; | 228 Pos[] q2; 71 foreach(p; q) { | 229 foreach(p; q) { 72 int[] dy=[-1,+1,0,0]; < 73 int[] dx=[0,0,-1,+1]; < > 230 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; > 231 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; 74 for(int i=0; i<4; ++i) { | 232 for(int i=0; i<yyy.length; ++i) { 75 int y = p.y+dy[i]; | 233 int y = yyy[i]; 76 int x = p.x+dx[i]; | 234 int x = xxx[i]; > 235 if('1'<=g[y,x]&&g[y,x]<='9') { > 236 foreach(ppp; g.trampolin > 237 yyy ~= ppp.y; > 238 xxx ~= ppp.x; > 239 } > 240 continue; > 241 } 77 if(v[y][x]) continue; | 242 if(v[y][x]) continue; 78 if(y==s.y && x==s.x) { | 243 if(y==s.y && x==s.x && i<4) { 79 if(i==0) return tuple('U',step); < 80 if(i==1) return tuple('D',step); < 81 if(i==2) return tuple('R',step); < 82 if(i==3) return tuple('L',step); < 83 } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { < > 244 char c = "UDRL"[i]; > 245 if( death.count(c) == 0 > 246 return [tuple(c, > 247 } else if(forbidden_cell[y][x]){ > 248 } else if(g[y,x]==' '||g[y,x]==' 84 q2 ~= new Pos(y,x); | 249 q2 ~= new Pos(y,x); 85 v[y][x]=true; | 250 v[y][x]=true; 86 } else if(g.map[y,x]=='.'/* && g[y-1,x]!='*'*/) < > 251 } > 252 } > 253 } > 254 q = q2; > 255 } > 256 return []; > 257 } > 258 > 259 // push rocks! > 260 Tuple!(char,int)[] tryC() { > 261 const(Pos)[] q; > 262 foreach(p; gs) q ~= p; > 263 bool[][] v = new bool[][](g.H+2, g.W+2); > 264 foreach(p; q) v[p.y][p.x]=true; > 265 for(int step=20; q.length; ++step) { > 266 Pos[] q2; > 267 foreach(p; q) { > 268 int[] yyy=[p.y-1,p.y+1,p.y,p.y]; > 269 int[] xxx=[p.x,p.x,p.x-1,p.x+1]; > 270 for(int i=0; i<yyy.length; ++i) { > 271 int y = yyy[i]; > 272 int x = xxx[i]; > 273 if(g[p] == '*') { > 274 if(i>=4)continue; > 275 if(y!=p.y)continue; > 276 if(g[y,p.x+(p.x-x)]!=' ' > 277 } > 278 if('1'<=g[y,x]&&g[y,x]<='9') { > 279 foreach(ppp; g.trampolin > 280 yyy ~= ppp.y; > 281 xxx ~= ppp.x; > 282 } > 283 continue; > 284 } > 285 if(v[y][x]) continue; > 286 if(y==s.y && x==s.x && i<4) { > 287 char c = "UDRL"[i]; > 288 if( death.count(c) == 0 > 289 return [tuple(c, > 290 } else if(forbidden_cell[y][x]){ > 291 } else if(g[y,x]==' '||g[y,x]==' 87 q2 ~= new Pos(y,x); | 292 q2 ~= new Pos(y,x); 88 v[y][x]=true; | 293 v[y][x]=true; > 294 } > 295 } 89 } 296 } > 297 q = q2; 90 } 298 } > 299 return []; 91 } 300 } 92 q = q2; | 301 return (danger_ok ? [] : tryA()) ~ tryB() ~ tryC(); 93 } 302 } 94 return tuple('W', int.max); < 95 } 303 } 96 304 97 void main(string[] args) | 305 class Solver_2(Solver) 98 { 306 { 99 auto g = Game.load(stdin); | 307 string plan; 100 g.set_output(new GuardedOutput(g)); | 308 bool plan_broken = true; > 309 > 310 Game g; > 311 this(in Game g) > 312 { > 313 this.g = g.clone(); > 314 make_plan(g); > 315 } > 316 > 317 Tuple!(Solver,string) run_sub_solver(in Game g) > 318 { > 319 string log; > 320 auto s = new Solver(g); > 321 while(!g.cleared && !g.dead && plan.length<=g.H*g.W) { > 322 char c = s.single_step(); > 323 if( c == 'A' ) > 324 break; > 325 log ~= c; > 326 } > 327 while(log.length>0 && log[$-1]=='W') > 328 log.length--; > 329 return tuple(s, log); > 330 } > 331 > 332 void make_plan(in Game g) { > 333 plan_broken = false; > 334 Tuple!(Solver,string) x = run_sub_solver(g); > 335 plan = x[1]; > 336 if(x[0].g.cleared) > 337 return; > 338 modify_plan(g, x[0].g.score); > 339 } > 340 > 341 void modify_plan(in Game ini, long unmod) > 342 { > 343 int bp = max(0, (cast(int)plan.length)-10); > 344 Game g = ini.clone(); > 345 for(int i=0; i<bp; ++i) g.command(plan[i]); > 346 > 347 Tuple!(string,long) cand = tuple(plan, unmod); > 348 for(int i=bp; i<plan.length; ++i) { > 349 foreach(string c; ["U","D","L","R","UD","DU","LR","RL"]) > 350 if(c[0] != plan[i]) { > 351 Tuple!(string,long) zz = try_plan(c, g); > 352 if(cand[1]<zz[1]) > 353 cand = tuple(plan[0..i]~c~zz[0], > 354 } > 355 g.command(plan[i]); > 356 } > 357 plan = cand[0]; > 358 } > 359 > 360 Tuple!(string,long) try_plan(string c, in Game g) > 361 { > 362 Game gg = g.clone(); > 363 foreach(cc;c)gg.command(cc); > 364 Tuple!(Solver, string) x = run_sub_solver(gg); > 365 return tuple(x[1], x[0].g.score); > 366 } > 367 > 368 char single_step() { > 369 if(plan_broken) > 370 make_plan(g); > 371 if(plan.empty) > 372 return 'A'; > 373 char c = plan[0]; > 374 plan = plan[1..$]; > 375 g.command(c); > 376 return c; > 377 } 101 378 102 while(!g.dead && !g.cleared) | 379 void force(char c) { 103 act(g); | 380 g.command(c); > 381 if(plan.length==0 || plan[0]!=c) { > 382 plan = ""; > 383 plan_broken = true; > 384 } > 385 else > 386 plan = plan[1..$]; > 387 } 104 } 388 } > 389 > 390 alias Solver_2!(Solver_1) MainSolver; > 391 //alias Solver_1 MainSolver;

Deleted src/test.d version [d9955daaabe58d54]

1 import std.algorithm; < 2 import std.array; < 3 import std.conv; < 4 import std.stdio; < 5 import std.string; < 6 import std.typecons; < 7 import core.stdc.signal; < 8 import core.stdc.stdlib; < 9 import dfl.all; < 10 < 11 class Map < 12 { < 13 private char[][] data; < 14 bool dead = false; < 15 bool cleared = false; < 16 int water = 0; < 17 int flooding = 0; < 18 int water_proof = 10; < 19 int underwater = 0; < 20 int flooding_counter = 0; < 21 < 22 this(File input) < 23 { < 24 string line; < 25 while( (line=input.readln().chomp()).length ) < 26 data ~= line.dup; < 27 < 28 int width = 0; < 29 foreach(s; data) < 30 width = max(width, s.length); < 31 < 32 // space padding and sentinels < 33 foreach(ref s; data) { < 34 int p = s.length; < 35 s.length = width; < 36 s[p..$] = ' '; < 37 s = '#' ~ s ~ '#'; < 38 } < 39 < 40 // vertical sentinel < 41 char[] sen = new char[width+2]; < 42 sen[] = '#'; < 43 data = sen.dup ~ data ~ sen; < 44 < 45 // flooding < 46 water = H-1; < 47 while( (line=input.readln()).length ) { < 48 string[] ss = line.split(); < 49 if(ss.length==2 && ss[0]=="Water") < 50 water = H-1 - ss[1].to!int(); < 51 else if(ss.length==2 && ss[0]=="Flooding") < 52 flooding = ss[1].to!int(); < 53 else if(ss.length==2 && ss[0]=="Waterproof") < 54 water_proof = ss[1].to!int(); < 55 } < 56 } < 57 < 58 @property const < 59 { < 60 int W() { return data[0].length; } < 61 int H() { return data.length; } < 62 string toString() { < 63 string result; < 64 foreach(i,s; data) { < 65 if(i) result ~= '\n'; < 66 result ~= s.idup; < 67 } < 68 return result; < 69 } < 70 } < 71 < 72 int command_R() { if(dead)return 0; write("R"); return move(0, +1); } < 73 int command_L() { if(dead)return 0; write("L"); return move(0, -1); } < 74 int command_U() { if(dead)return 0; write("U"); return move(-1, 0); } < 75 int command_D() { if(dead)return 0; write("D"); return move(+1, 0); } < 76 int wait() { if(dead)return 0; update(); write("W"); return -1; } < 77 int abort() { if(dead)return 0; cleared=true; write("A"); return gained* < 78 < 79 int move(int dy, int dx) { < 80 foreach(y,s; data) < 81 foreach(x,c; s) < 82 if(c == 'R') < 83 return move(dy, dx, y, x); < 84 assert(false); < 85 } < 86 < 87 int gained = 0; // TODO: atode naosu < 88 int move(int dy, int dx, int y, int x) { < 89 if(dead) < 90 return 0; < 91 int score = 0; < 92 if(data[y+dy][x+dx]=='\\') { < 93 score += 25; < 94 ++gained; < 95 } < 96 if(data[y+dy][x+dx]=='O') { < 97 score += gained*50; < 98 cleared = true; < 99 } < 100 < 101 if(data[y+dy][x+dx]==' ' || data[y+dy][x+dx]=='.' < 102 || data[y+dy][x+dx]=='\\' || data[y+dy][x+dx]=='O') { < 103 data[y][x]=' '; < 104 data[y+dy][x+dx]='R'; < 105 } else if(dy==0 && data[y+dy][x+dx]=='*' && data[y+2*dy][x+2*dx] < 106 data[y][x]=' '; < 107 data[y+dy][x+dx]='R'; < 108 data[y+2*dy][x+2*dx]='*'; < 109 } < 110 update(); < 111 return score-1; < 112 } < 113 < 114 void update() { < 115 char[][] next; < 116 foreach(y,s; data) < 117 next ~= s.dup; < 118 < 119 bool lambda = false; < 120 for(int y=1; y+1<H; ++y) < 121 for(int x=1; x+1<W; ++x) < 122 lambda |= (data[y][x] == '\\'); < 123 < 124 for(int y=H-2; y>=1; --y) < 125 for(int x=1; x+1<W; ++x) { < 126 if(data[y][x]=='*') { < 127 if(data[y+1][x]==' ') { < 128 next[y][x]=' '; < 129 next[y+1][x]='*'; < 130 if(next[y+2][x]=='R') < 131 dead=true; < 132 } < 133 else if(data[y+1][x]=='*' && data[y][x+1]==' ' & < 134 next[y][x]=' '; < 135 next[y+1][x+1]='*'; < 136 if(next[y+2][x+1]=='R') < 137 dead=true; < 138 } < 139 else if(data[y+1][x]=='*' && data[y][x-1]==' ' & < 140 next[y][x]=' '; < 141 next[y+1][x-1]='*'; < 142 if(next[y+2][x-1]=='R') < 143 dead=true; < 144 } < 145 else if(data[y+1][x]=='\\' && data[y][x+1]==' ' < 146 next[y][x]=' '; < 147 next[y+1][x+1]='*'; < 148 if(next[y+2][x+1]=='R') < 149 dead=true; < 150 } < 151 } < 152 else if(data[y][x]=='L') { < 153 if(!lambda) < 154 next[y][x] = 'O'; < 155 } < 156 } < 157 data = next; < 158 < 159 if(flooding) { < 160 bool wa = false; < 161 for(int y=water; y+1<H; ++y) < 162 for(int x=1; x+1<W; ++x) < 163 if(data[y][x]=='R') { < 164 wa = true; < 165 underwater++; < 166 if(underwater > water_proof) < 167 dead = true; < 168 } < 169 flooding_counter ++; < 170 if(flooding_counter == flooding) { < 171 flooding_counter = 0; < 172 water --; < 173 } < 174 } < 175 } < 176 < 177 int clever() < 178 { < 179 if(dead) < 180 return 0; < 181 int sy,sx; < 182 int[] ly,lx; < 183 int oy,ox; < 184 for(int y=0; y<H; ++y) < 185 for(int x=0; x<W; ++x) < 186 if(data[y][x]=='R') < 187 sy=y, sx=x; < 188 else if(data[y][x]=='\\') < 189 ly~=y, lx~=x; < 190 else if(data[y][x]=='O') < 191 oy=y, ox=x; < 192 if(ly.length==0) { < 193 auto r = search(sy,sx,oy,ox); < 194 switch(r[0]) { < 195 case 'D': return command_D(); < 196 case 'U': return command_U(); < 197 case 'L': return command_L(); < 198 case 'R': return command_R(); < 199 case 'A': return abort(); < 200 default: return wait(); < 201 } < 202 } else { < 203 Tuple!(char,int)[] cand; < 204 for(int i=0; i<ly.length; ++i) { < 205 auto r = search(sy,sx,ly[i],lx[i]); < 206 cand ~= r; < 207 } < 208 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ < 209 if(c1[1] != c2[1]) < 210 return c1[1] < c2[1]; < 211 return c1[0] < c2[0]; < 212 })(cand); < 213 switch(cand[0][0]) { < 214 case 'D': return command_D(); < 215 case 'U': return command_U(); < 216 case 'L': return command_L(); < 217 case 'R': return command_R(); < 218 case 'A': return abort(); < 219 default: return wait(); < 220 } < 221 } < 222 return wait(); < 223 } < 224 Tuple!(char,int) search(int sy, int sx, int oy, int ox) < 225 { < 226 alias Tuple!(int,"y",int,"x") Pt; < 227 Pt[] q = [Pt(oy,ox)]; < 228 bool[][] v = new bool[][](H,W); < 229 for(int step=1; q.length; ++step) { < 230 Pt[] q2; < 231 foreach(p; q) { < 232 int[] dy=[-1,+1,0,0]; < 233 int[] dx=[0,0,-1,+1]; < 234 for(int i=0; i<4; ++i) { < 235 int y = p.y+dy[i]; < 236 int x = p.x+dx[i]; < 237 if(v[y][x]) continue; < 238 if(y==sy && x==sx) { < 239 if(i==0) return tuple('D',step); < 240 if(i==1) return tuple('U',step); < 241 if(i==2) return tuple('R',step); < 242 if(i==3) return tuple('L',step); < 243 } else if(data[y][x]==' '||data[y][x]==' < 244 q2 ~= Pt(y,x); < 245 v[y][x]=true; < 246 } else if(data[y][x]=='.' && data[y-1][x < 247 q2 ~= Pt(y,x); < 248 v[y][x]=true; < 249 } < 250 } < 251 } < 252 q = q2; < 253 } < 254 q = [Pt(oy,ox)]; < 255 v = new bool[][](H,W); < 256 for(int step=1<<10; q.length; ++step) { < 257 Pt[] q2; < 258 foreach(p; q) { < 259 < 260 int[] dy=[-1,+1,0,0]; < 261 int[] dx=[0,0,-1,+1]; < 262 for(int i=0; i<4; ++i) { < 263 int y = p.y+dy[i]; < 264 int x = p.x+dx[i]; < 265 if(v[y][x]) continue; < 266 if(y==sy && x==sx) { < 267 if(i==0) return tuple('D',step); < 268 if(i==1) return tuple('U',step); < 269 if(i==2) return tuple('R',step); < 270 if(i==3) return tuple('L',step); < 271 } else if(data[y][x]==' '||data[y][x]==' < 272 q2 ~= Pt(y,x); < 273 v[y][x]=true; < 274 } else if(data[y][x]=='.'/* && data[y-1] < 275 q2 ~= Pt(y,x); < 276 v[y][x]=true; < 277 } < 278 } < 279 } < 280 q = q2; < 281 } < 282 return tuple('A',int.max); < 283 } < 284 } < 285 < 286 class MyForm : Form < 287 { < 288 Map m; < 289 int score; < 290 < 291 this(Map m) < 292 { < 293 noMessageFilter(); < 294 this.m = m; < 295 this.text = .text("Score: ", score, " air[",m.water_proof-m.und < 296 this.keyDown ~= &myKey; < 297 this.score = 0; < 298 } < 299 override void onResize(EventArgs ev) { < 300 invalidate(); < 301 } < 302 override void onPaint(PaintEventArgs ev) < 303 { < 304 int Z = min(this.clientSize.width/(m.W-2), this.clientSize.heigh < 305 Font font = new Font("MS Gothic", Z-4); < 306 Graphics g = ev.graphics; < 307 g.fillRectangle(Color(0,233,255), Rect(0,Z*(m.water-1),this.clie < 308 for(int y=1; y+1<m.H; ++y) < 309 for(int x=1; x+1<m.W; ++x) { < 310 if(m.data[y][x]=='*') { < 311 g.drawText("岩", font, Color(0,0,0), Rect((x-1)*Z < 312 } < 313 if(m.data[y][x]=='\\') { < 314 g.drawText("λ", font, Color(0,255,0), Rect((x-1) < 315 } < 316 if(m.data[y][x]=='R') { < 317 if(m.dead) < 318 g.drawText("Я", font, Color(255,0,0), Re < 319 else < 320 g.drawText("R", font, Color(128,128,0), < 321 } < 322 if(m.data[y][x]=='L') { < 323 g.drawText("扉", font, Color(255,255,0), Rect((x- < 324 } < 325 if(m.data[y][x]=='O') { < 326 g.drawText("外", font, Color(255,255,0), Rect((x- < 327 } < 328 if(m.data[y][x]=='#') { < 329 g.drawText("#", font, Color(0,0,0), Rect((x-1)*Z < 330 } < 331 if(m.data[y][x]=='.') { < 332 g.drawText("・", font, Color(128,40,0), Rect((x-1 < 333 } < 334 } < 335 } < 336 void myKey(Control c, KeyEventArgs ev) < 337 { < 338 switch(ev.keyCode) < 339 { < 340 case Keys.DOWN: < 341 score += m.command_D(); < 342 stdout.flush(); < 343 break; < 344 case Keys.UP: < 345 score += m.command_U(); < 346 stdout.flush(); < 347 break; < 348 case Keys.LEFT: < 349 score += m.command_L(); < 350 stdout.flush(); < 351 break; < 352 case Keys.RIGHT: < 353 score += m.command_R(); < 354 stdout.flush(); < 355 break; < 356 case Keys.W: < 357 score += m.wait(); < 358 stdout.flush(); < 359 break; < 360 case Keys.A: < 361 score += m.abort(); < 362 stdout.flush(); < 363 break; < 364 case Keys.G: < 365 score += m.clever(); < 366 stdout.flush(); < 367 break; < 368 default: < 369 break; < 370 } < 371 if(m.cleared) { < 372 writeln(); < 373 writeln("Score: ", score); < 374 Application.exit(); < 375 } < 376 this.text = .text("Score: ", score, " air[",m.water_proof-m.und < 377 invalidate(); < 378 } < 379 } < 380 < 381 extern(C) { < 382 void sigint(int) { < 383 write("A"); < 384 stdout.flush(); < 385 exit(0); < 386 } < 387 } < 388 < 389 void main(string[] args) < 390 { < 391 signal(SIGINT, &sigint); < 392 < 393 Form myForm = new MyForm(new Map(File(args[1]))); < 394 Application.run(myForm); < 395 } <

Modified src/util.d from [783554bf667412ed] to [b76be1f6ad977d56].

1 public import std.algorithm; 1 public import std.algorithm; 2 public import std.array; 2 public import std.array; 3 public import std.conv; 3 public import std.conv; 4 public import std.range; 4 public import std.range; 5 public import std.stdio; 5 public import std.stdio; 6 public import std.string; 6 public import std.string; 7 public import std.typecons; 7 public import std.typecons; > 8 public import std.math; 8 import std.c.stdlib; 9 import std.c.stdlib; > 10 > 11 T[] erase(T,V)(T[] xs, V y) > 12 { > 13 foreach(i,x; xs) > 14 if(x == y) > 15 return xs[0..i]~xs[i+1..$]; > 16 return xs; > 17 } > 18 > 19 // To avoide the following ICE: > 20 // src\phobos\std\algorithm.d(4552): > 21 // Error: function std.algorithm.count!("a == b",string,char).count > 22 // compiler error, parameter 'value', bugzilla 2962? > 23 // Assertion failure: '0' on line 717 in file 'glue.c' > 24 int count(T,V)(T[] a, V v) > 25 { > 26 int cnt = 0; > 27 foreach(e; a) > 28 if(e == v) > 29 ++cnt; > 30 return cnt; > 31 } 9 32 10 void application_exit() 33 void application_exit() 11 { 34 { 12 std.c.stdlib.exit(0); 35 std.c.stdlib.exit(0); 13 } 36 } 14 37 15 template DeriveCreate() 38 template DeriveCreate() ................................................................................................................................................................................ 19 this.tupleof = params; 42 this.tupleof = params; 20 } 43 } 21 } 44 } 22 45 23 template DeriveCompare() 46 template DeriveCompare() 24 { 47 { 25 override: 48 override: 26 bool opEquals(Object rhs) | 49 bool opEquals(Object rhs) const 27 { 50 { 28 return tuple(this.tupleof) == tuple((cast(typeof(this))rhs).tupl 51 return tuple(this.tupleof) == tuple((cast(typeof(this))rhs).tupl 29 } 52 } 30 53 31 int opCmp(Object rhs) | 54 int opCmp(Object rhs) const 32 { 55 { 33 return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).t 56 return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).t 34 } 57 } 35 58 36 hash_t toHash() | 59 hash_t toHash() const 37 { 60 { 38 hash_t v = 0; 61 hash_t v = 0; 39 foreach(mem; this.tupleof) { 62 foreach(mem; this.tupleof) { 40 v *= 11; 63 v *= 11; 41 static if(__traits(compiles, v^=mem)) 64 static if(__traits(compiles, v^=mem)) 42 v ^= mem; 65 v ^= mem; 43 else 66 else ................................................................................................................................................................................ 46 return v; 69 return v; 47 } 70 } 48 } 71 } 49 72 50 template DeriveShow() 73 template DeriveShow() 51 { 74 { 52 override: 75 override: 53 string toString() | 76 string toString() const 54 { 77 { 55 string str = text(typeof(this).stringof, "("); 78 string str = text(typeof(this).stringof, "("); 56 foreach(i,mem; this.tupleof) { 79 foreach(i,mem; this.tupleof) { 57 if(i) str ~= ", "; 80 if(i) str ~= ", "; 58 str = text(str, this.tupleof[i].stringof[5..$], ":", me 81 str = text(str, this.tupleof[i].stringof[5..$], ":", me 59 } 82 } 60 return str ~ ")"; 83 return str ~ ")"; 61 } 84 } 62 } 85 }

Modified submission/README from [0cf14a3b96651332] to [9ce063855f41ff05].

> 1 Team: 1 Team "Dark Integers". | 2 Dark Integers 2 < 3 Member: 3 Member: 4 Kazuhiro Inaba (www.kmonos.net / kiki@kmonos.net) 4 Kazuhiro Inaba (www.kmonos.net / kiki@kmonos.net) 5 Language: 5 Language: 6 D Programming Language (dlang.org) 6 D Programming Language (dlang.org) 7 7 8 This submission for lightning division is not particulary interseting. 8 This submission for lightning division is not particulary interseting. 9 9 ................................................................................................................................................................................ 18 trims the command history and inserts the 'A'bort at the optimal timing. 18 trims the command history and inserts the 'A'bort at the optimal timing. 19 This is also used for SIGINT handling. 19 This is also used for SIGINT handling. 20 20 21 - gui.d is a windows GUI for the game, using DFL (http://github.com/Rayerd/dfl) 21 - gui.d is a windows GUI for the game, using DFL (http://github.com/Rayerd/dfl) 22 it is not compiled into the submitted routine. This is just a helper. 22 it is not compiled into the submitted routine. This is just a helper. 23 23 24 Stay tuned for the full submission, judges! 24 Stay tuned for the full submission, judges! 25 <