Check-in Differences
Not logged in

Difference From:

[6293256fec] Preparing for submission... (user: kinaba, tags: trunk, date: 2012-07-14 09:16:47)

To:

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

Added icfp-96533632.tgz version [943329c30072989f]

cannot compute difference between binary files

Added make-submission version [bd7a911c141ae544]

1 +#!/bin/sh 2 +rm -rf submission/src 3 +cp -r src submission/src 4 +tar czf icfp-96533632.tgz submission

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.d solver.d util.d

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(fin)log~="$"; } 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 [7c15481493257083] to [fc05481901940844].

1 1 import util; 2 -import output; 3 2 4 3 //////////////////////////////////////////////////////////////////////////////// 5 4 6 5 class Pos 7 6 { 8 7 public immutable int y, x; 9 8 mixin DeriveCreate; 10 9 mixin DeriveCompare; 11 10 mixin DeriveShow; 12 - Pos clone() { return this; } 11 + Pos clone() const { return cast(Pos) this; } 13 12 14 13 @property: 15 - Pos wait() { return this; } 14 + Pos wait() { return this.clone(); } 16 15 Pos up() { return new Pos(y+1, x); } 17 16 Pos down() { return new Pos(y-1, x); } 18 17 Pos left() { return new Pos(y, x-1); } 19 18 Pos right() { return new Pos(y, x+1); } 20 19 alias wait W,w; 21 20 alias up U,u; 22 21 alias down D,d; ................................................................................ 42 41 43 42 class Water 44 43 { 45 44 public immutable int base, pace; 46 45 mixin DeriveCreate; 47 46 mixin DeriveCompare; 48 47 mixin DeriveShow; 49 - Water clone() { return this; } 48 + Water clone() const { return cast(Water)this; } 50 49 51 50 static load(string[string] params) 52 51 { 53 - return new Water( 54 - params.get("Water", "0").to!int(), 55 - params.get("Flooding", "0").to!int() 56 - ); 52 + return new Water(params.get("Water", "0").to!int(), 53 + params.get("Flooding", "0").to!int()); 57 54 } 58 55 59 - int level(int number_of_update) 56 + int level(int number_of_update) const 60 57 { 61 58 return pace ? base+(number_of_update/pace) : base; 62 59 } 63 60 64 - int until_rise(int number_of_update) 61 + int until_rise(int number_of_update) const 65 62 { 66 63 return pace ? pace-number_of_update%pace : int.max; 67 64 } 68 65 } 69 66 70 67 unittest 71 68 { ................................................................................ 85 82 assert( 1 == w.level(3) ); 86 83 assert( 1 == w.level(4) ); 87 84 assert( 1 == w.level(5) ); 88 85 } 89 86 90 87 //////////////////////////////////////////////////////////////////////////////// 91 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 + 92 115 class Map 93 116 { 94 117 mixin DeriveShow; 95 118 96 - static Map load(string[] raw_data, string[string] params) 119 + static Map load(string[] raw_data, string[string] params, char[char] trampo) 97 120 { 98 121 // TODO: choose optimal representation. 99 - return new Map(raw_data, params); 122 + return new Map(raw_data, params, trampo); 100 123 } 101 124 102 125 char[][] data; 103 126 Pos robot; 104 127 Pos lift; 105 128 int waterproof; 129 + Pos[char] tr_target; 130 + Pos[][char] tr_source; 131 + const(Hige) hige; 132 + int razor; 106 133 107 - Map clone() { return new Map(this); } 108 - this(Map m) { 134 + Map clone() const { return new Map(this); } 135 + this(in Map m) { 109 136 foreach(s; m.data) 110 137 this.data ~= s.dup; 111 138 this.robot = m.robot.clone(); 112 139 this.lift = m.lift.clone(); 113 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; 114 145 } 115 146 116 - this(string[] raw_data, string[string] params) 147 + this(string[] raw_data, string[string] params, char[char] trampo) 117 148 { 118 149 int width = 0; 119 150 foreach(r; raw_data) 120 151 width = max(width, r.length); 121 152 foreach(r; raw_data) { 122 153 this.data ~= r.dup; 123 154 this.data[$-1].length = width; ................................................................................ 127 158 for(int y=1; y<=H; ++y) 128 159 for(int x=1; x<=W; ++x) { 129 160 if(this[y,x] == 'R') 130 161 this.robot = new Pos(y,x); 131 162 if(this[y,x] == 'L' || this[y,x] == 'O') 132 163 this.lift = new Pos(y,x); 133 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 + } 134 173 135 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(); 136 183 } 137 184 138 185 const @property { 139 186 int H() { return data.length; } 140 187 int W() { return data[0].length; } 141 188 } 142 189 143 - char opIndex(int y, int x) 144 - { 145 - // Adjust coordinate to the spec. bottom-left is (1,1). 146 - --y, --x; 147 - if(y<0||H<=y||x<0||W<=x) 148 - return '#'; 149 - return data[H-1-y][x]; 150 - } 190 + const { 191 + char opIndex(int y, int x) 192 + { 193 + // Adjust coordinate to the spec. bottom-left is (1,1). 194 + --y, --x; 195 + if(y<0||H<=y||x<0||W<=x) 196 + return '#'; 197 + return data[H-1-y][x]; 198 + } 151 199 152 - char opIndex(Pos p) 153 - { 154 - return this[p.y, p.x]; 200 + char opIndex(in Pos p) 201 + { 202 + return this[p.y, p.x]; 203 + } 155 204 } 156 205 157 206 void opIndexAssign(char c, int y, int x) 158 207 { 159 208 // Adjust coordinate to the spec. bottom-left is (1,1). 160 209 --y, --x; 161 210 if(y<0||H<=y||x<0||W<=x) 162 211 return; 163 212 data[H-1-y][x] = c; 164 213 } 165 214 166 - void opIndexAssign(char c, Pos p) 215 + void opIndexAssign(char c, in Pos p) 167 216 { 168 217 this[p.y, p.x] = c; 169 218 } 170 219 171 - Pos[] lambdas() { 220 + Pos[] objects(char c) const { 172 221 Pos[] ans; 173 222 for(int y=1; y<=H; ++y) 174 223 for(int x=1; x<=W; ++x) 175 - if(this[y,x] == '\\') 224 + if(this[y,x] == c) 176 225 ans ~= new Pos(y,x); 177 226 return ans; 178 227 } 179 228 180 - bool cleared() 229 + Pos[] razors() const { return objects('!'); } 230 + Pos[] lambdas() const { return objects('\\'); } 231 + 232 + bool cleared() const 181 233 { 182 234 for(int y=1; y<=H; ++y) 183 235 for(int x=1; x<=W; ++x) 184 236 if(this[y,x] == 'L' || this[y,x] == 'O') 185 237 return false; 186 238 return true; 187 239 } 188 240 189 - Tuple!(int,bool) command(char c) 241 + Tuple!(int,bool) command(char c, int turn) 190 242 { 191 - if(c=='R') return move( 0, +1); 192 - if(c=='L') return move( 0, -1); 193 - if(c=='U') return move(+1, 0); 194 - if(c=='D') return move(-1, 0); 195 - if(c=='W') return move( 0, 0); 243 + assert( this[robot] == 'R' ); 244 + if(c=='R') return move( 0, +1, turn); 245 + if(c=='L') return move( 0, -1, turn); 246 + if(c=='U') return move(+1, 0, turn); 247 + if(c=='D') return move(-1, 0, turn); 248 + if(c=='W') return move( 0, 0, turn); 249 + if(c=='S') return use_razor(turn); 196 250 assert(false); 197 251 } 198 252 199 - Tuple!(int, bool) move(int dy, int dx) 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 + 267 + Tuple!(int, bool) move(int dy, int dx, int turn) 200 268 { 201 269 int y = robot.y; 202 270 int x = robot.x; 203 - assert( this[robot] == 'R' ); 204 271 int lambda = 0; 205 - bool dead = false; 206 272 if( '\\' == this[y+dy,x+dx] ) 207 273 lambda++; 208 - if( " \\.O".count(this[y+dy,x+dx])==1 ) { 274 + if( '!' == this[y+dy,x+dx] ) 275 + razor++; 276 + if( " \\!.O".count(this[y+dy,x+dx])==1 ) { 209 277 this[y,x]=' '; 210 278 this[y+dy,x+dx]='R'; 211 279 robot = new Pos(y+dy,x+dx); 212 280 } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx*2]) { 213 281 this[y,x]=' '; 214 282 this[y+dy,x+dx]='R'; 215 283 this[y+dy*2,x+dx*2]='*'; 216 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; 217 292 } 218 - if( update() ) 219 - dead = true; 293 + bool dead = update(turn); 220 294 return tuple(lambda,dead); 221 295 } 222 296 223 - bool update() 297 + bool update(int turn) 224 298 { 225 299 bool dead = false; 226 300 227 301 char[][] next; 228 302 foreach(y,s; data) 229 303 next ~= s.dup; 230 304 ................................................................................ 258 332 dead=true; 259 333 } 260 334 } 261 335 else if(this[p]=='L') { 262 336 if(!lambda) 263 337 access(p) = 'O'; 264 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.x+dx)) = 'W'; 345 + } 265 346 } 266 347 data = next; 267 348 return dead; 268 349 } 269 350 } 270 351 271 352 //////////////////////////////////////////////////////////////////////////////// 272 353 273 354 class Game 274 355 { 275 - mixin DeriveShow; 276 - 277 - static Game load(File input) 356 +public: 357 + this(File input) 278 358 { 279 - string[] raw_data; 280 - string[string] params; 281 - 282 - // Raw map data; read until empty line. 359 + // Read map data 360 + string[] map_data_lines; 283 361 for(string line; !(line=input.readln().chomp()).empty; ) 284 - raw_data ~= line; 362 + map_data_lines ~= line; 285 363 286 - // Additional commands; read until EOF. 287 - for(string line; !(line=input.readln()).empty; ) { 364 + // H*W 365 + H_ = map_data_lines.length; 366 + W_ = 0; 367 + foreach(mdl; map_data_lines) 368 + W_ = max(W_, mdl.length); 369 + 370 + // Copy to modifiable buffer and adjust coordinates. 371 + raw_data_ = new char[][H_+1]; 372 + foreach(i,mdl; map_data_lines) { 373 + char[] buf = new char[mdl.length+1]; 374 + buf[0] = '#'; 375 + buf[1..$] = mdl[]; 376 + raw_data_[H_-i] = buf; 377 + } 378 + 379 + // Detect objects 380 + for(int y=1; y<=H_; ++y) 381 + for(int x=1; x<raw_data_[y].length; ++x) 382 + { 383 + char c = raw_data_[y][x]; 384 + switch(c) 385 + { 386 + case '#': 387 + case '.': 388 + case ' ': 389 + break; 390 + case 'L': 391 + case 'O': 392 + lift_pos_ = new Pos(y,x); 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; 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); 419 + } 420 + } 421 + 422 + // Read other parameters 423 + for(string line; !(line=input.readln()).empty; ) 424 + { 288 425 string[] ss = line.split(); 289 426 if( ss.length == 2 ) 290 - params[ss[0]] = ss[1]; 427 + switch(ss[0]) 428 + { 429 + case "Water": water_base_ = ss[1].to!int(); break; 430 + case "Flooding": water_pace_ = ss[1].to!int(); break; 431 + case "Waterproof": max_air_ = ss[1].to!int(); break; 432 + case "Growth": hige_pace_ = ss[1].to!int(); break; 433 + case "Razors": num_razor_ = ss[1].to!int(); break; 434 + default: assert(false); 435 + } 436 + if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" ) 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; 442 + } 443 + } 444 + 445 + air_left_ = max_air_; 446 + } 447 + 448 + @property const { 449 + int H() { return H_; } 450 + int W() { return W_; } 451 + char trampoline(char c) { return (c in trampoline_ ? trampoline_[c] : 0); } 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 + } 460 + int water_level() { 461 + return water_pace_ ? water_base_ + turn_/water_pace_ : water_base_; 462 + } 463 + int water_until_rise() { 464 + return water_pace_ ? water_pace_ - turn_%water_pace_ : int.max; 465 + } 466 + int hige_until_rise() { 467 + return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int.max; 468 + } 469 + bool is_hige_turn() { 470 + return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : false; 471 + } 472 + int hp() { return air_left_; } 473 + int num_razor() { return num_razor_; } 474 + bool cleared() { return cleared_; } 475 + bool dead() { return dead_; } 476 + long score() { return num_lambda_*(dead_ ? 25L : cleared_ ? 75L : 50L) - turn_; } 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; 291 497 } 292 - 293 - return load(raw_data, params); 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); } 294 502 } 295 503 296 - static Game load(string[] raw_data, string[string] params) 297 - { 298 - return new Game(raw_data, params); 299 - } 300 - 301 - this(string[] raw_data, string[string] params) 302 - { 303 - this.map = Map.load(raw_data, params); 304 - this.water = Water.load(params); 305 - this.output = new NilOutput; 306 - } 307 - 308 - Game clone() { return new Game(this); } 309 - this(Game g) { 310 - map = g.map.clone(); 311 - water = g.water.clone(); 312 - output = new NilOutput; 313 - turn = g.turn; 314 - dead = g.dead; 315 - lambda = g.lambda; 316 - exit_bonus = g.exit_bonus; 317 - under_water = g.under_water; 318 - } 319 - 320 - void set_output(Output o) { this.output = (o is null ? new NilOutput : o); } 321 - 504 +public: 322 505 void command(char c) 323 506 { 324 507 if(dead || cleared) 325 508 return; 326 - scope(exit) { 327 - if(dead || cleared) 328 - output.flush(); 329 - } 330 - this.output.command(c); 331 509 332 - if(c == 'A') 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) 333 518 { 334 - exit_bonus = 1; 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) 335 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 + } 336 577 } 578 + } 337 579 338 - // TODO: clarify the event order 339 - Tuple!(int,bool) ld = map.command(c); 340 - if( map.cleared() ) { 341 - exit_bonus = 2; 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); 342 601 } 343 - else { 344 - lambda += ld[0]; 345 - if( ld[1] ) { 346 - dead = true; 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]==' '&&this[y,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-1]==' ') { 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 + } 347 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; 348 686 } 349 - if( map.robot.y <= water_level ) 350 - ++under_water; 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_ --; 351 696 else 352 - under_water = 0; 353 - if( under_water > map.waterproof ) 354 - dead = true; 355 - turn += 1; 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_); 356 753 } 357 754 358 - Map map; 359 - Water water; 360 - Output output; 361 - int turn = 0; 362 - bool dead = false; 363 - int lambda = 0; 364 - int exit_bonus = 0; 365 - int under_water = 0; 366 - // TODO: when adding members, take care of clone(). 367 - // TODO: fix this poor design. 368 - 369 - @property { 370 - long score() { return lambda*25L*(1+exit_bonus) - turn; } 371 - int water_level() { return water.level(turn); } 372 - int water_until_rise() { return water.until_rise(turn); } 373 - bool cleared() { return exit_bonus>0; } 374 - int hp() { return map.waterproof - under_water; } 375 - long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus)) - turn; } 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; 376 759 } 377 -} 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; 378 779 379 -unittest 380 -{ 381 - Game.load(["###","...","#RL"], ["xxx":"yyy"]); 780 + int turn_ = 0; 781 + int air_left_ = 0; 782 + bool cleared_ = false; 783 + bool dead_ = false; 784 + bool[Pos] may_update_; 382 785 }

Modified src/gui.d from [8bca70d55515c665] to [e84cacd6262f93a7].

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

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

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

1 1 import util; 2 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 { 9 - Pos ro = g.map.robot; 10 - Pos[] la = g.map.lambdas(); 11 - Pos li = g.map.lift; 12 - 13 - char c = 'W'; 14 - if( la.empty ) { 15 - auto r = search(g, ro, li); 16 - c = r[0]; 17 - } else { 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 + { 59 + const Pos ro = g.robot; 60 + const Pos li = g.lift; 61 + Pos[] la = g.lambdas(); 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(); 69 + 18 70 Tuple!(char,int)[] cand; 19 - foreach(lam; la) 20 - cand ~= search(g, ro, lam); 71 + char c = 'W'; 72 + if( la.empty ) { 73 + cand = search(g, ro, [li], death); 74 + } else { 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,x+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 121 sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ 22 122 if(c1[1] != c2[1]) 23 123 return c1[1] < c2[1]; 24 124 return c1[0] < c2[0]; 25 125 })(cand); 26 126 c = cand[0][0]; 27 - } 28 - if(c=='W') { 29 - g_wc++; 30 - if(g_wc > 10) 127 + 128 + if(death.count(c) || wait_count>=2) { 129 + foreach(char live; "UDLRW") 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 141 c = 'A'; 32 - } 33 - else 34 - g_wc = 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) { 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 - } 142 + 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..$]; 149 + int cnt = 0; 150 + foreach(l; log) 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 } 67 - q = [o]; 68 - v = new bool[][](g.map.H+2, g.map.W+2); 69 - for(int step=1000; q.length; ++step) { 70 - Pos[] q2; 71 - foreach(p; q) { 72 - int[] dy=[-1,+1,0,0]; 73 - int[] dx=[0,0,-1,+1]; 74 - for(int i=0; i<4; ++i) { 75 - int y = p.y+dy[i]; 76 - int x = p.x+dx[i]; 77 - if(v[y][x]) continue; 78 - if(y==s.y && x==s.x) { 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]=='\\') { 84 - q2 ~= new Pos(y,x); 85 - v[y][x]=true; 86 - } else if(g.map[y,x]=='.'/* && g[y-1,x]!='*'*/) { 87 - q2 ~= new Pos(y,x); 88 - v[y][x]=true; 159 + 160 + Tuple!(char,int)[] search(in Game g, in Pos s, in Pos[] gs, string death, bool danger_ok=false) 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]=='*') && (g[y+1,x]==' '||g[y+1,x]=='R')) 169 + return true; 170 + if(g[y+1,x+1]=='*' && (g[y,x+1]=='*') && (g[y+1,x]==' '||g[y+1,x]=='R')) 171 + return true; 172 + if(g[y,x-1]=='*' && (g[y-1,x-1]=='\\'||g[y-1,x-1]=='*') && (g[y-1,x]==' '||g[y-1,x]=='R')) 173 + return true; 174 + if(g[y,x+1]=='*' && (g[y-1,x+1]=='*') && (g[y-1,x]==' '||g[y-1,x]=='R')) 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.trampoline_rev(g[y,x])) { 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,step)]; 207 + } else if(forbidden_cell[y][x]){ 208 + } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='!'||i>=4) { 209 + if(danger(y,x)) 210 + continue; 211 + q2 ~= new Pos(y,x); 212 + v[y][x]=true; 213 + } 214 + } 215 + } 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; 225 + bool[][] v = new bool[][](g.H+2, g.W+2); 226 + foreach(p; q) v[p.y][p.x]=true; 227 + for(int step=10; q.length; ++step) { 228 + Pos[] q2; 229 + foreach(p; q) { 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]; 232 + for(int i=0; i<yyy.length; ++i) { 233 + int y = yyy[i]; 234 + int x = xxx[i]; 235 + if('1'<=g[y,x]&&g[y,x]<='9') { 236 + foreach(ppp; g.trampoline_rev(g[y,x])) { 237 + yyy ~= ppp.y; 238 + xxx ~= ppp.x; 239 + } 240 + continue; 241 + } 242 + if(v[y][x]) continue; 243 + if(y==s.y && x==s.x && i<4) { 244 + char c = "UDRL"[i]; 245 + if( death.count(c) == 0 ) 246 + return [tuple(c,step)]; 247 + } else if(forbidden_cell[y][x]){ 248 + } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='!'||i>=4) { 249 + q2 ~= new Pos(y,x); 250 + v[y][x]=true; 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)]!=' '&&g[y,p.x+(p.x-x)]!='R')continue; 277 + } 278 + if('1'<=g[y,x]&&g[y,x]<='9') { 279 + foreach(ppp; g.trampoline_rev(g[y,x])) { 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,step)]; 290 + } else if(forbidden_cell[y][x]){ 291 + } else if(g[y,x]==' '||g[y,x]=='\\'||g[y,x]=='.'||g[y,x]=='*'||g[y,x]=='!'||i>=4) { 292 + q2 ~= new Pos(y,x); 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); 100 - g.set_output(new GuardedOutput(g)); 307 + string plan; 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], zz[1]); 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) 103 - act(g); 379 + void force(char c) { 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*25; } 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]==' ' && data[y+1][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]==' ' && data[y+1][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]==' ' && data[y+1][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][x]!='*'*/) { 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.underwater,"]"); 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.height/(m.H-2)); 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.clientSize.width,this.clientSize.height-(Z*(m.water-1)))); 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, (y-1)*Z, Z, Z)); 312 - } 313 - if(m.data[y][x]=='\\') { 314 - g.drawText("λ", font, Color(0,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 315 - } 316 - if(m.data[y][x]=='R') { 317 - if(m.dead) 318 - g.drawText("Я", font, Color(255,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 319 - else 320 - g.drawText("R", font, Color(128,128,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 321 - } 322 - if(m.data[y][x]=='L') { 323 - g.drawText("扉", font, Color(255,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 324 - } 325 - if(m.data[y][x]=='O') { 326 - g.drawText("外", font, Color(255,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 327 - } 328 - if(m.data[y][x]=='#') { 329 - g.drawText("#", font, Color(0,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 330 - } 331 - if(m.data[y][x]=='.') { 332 - g.drawText("・", font, Color(128,40,0), Rect((x-1)*Z, (y-1)*Z, Z, Z)); 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.underwater,"]"); 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 [8d98b81c5616ea88] to [b76be1f6ad977d56].

1 1 public import std.algorithm; 2 2 public import std.array; 3 3 public import std.conv; 4 4 public import std.range; 5 5 public import std.stdio; 6 6 public import std.string; 7 7 public import std.typecons; 8 +public import std.math; 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 +} 32 + 33 +void application_exit() 34 +{ 35 + std.c.stdlib.exit(0); 36 +} 8 37 9 38 template DeriveCreate() 10 39 { 11 40 this(TS...)(TS params) 12 41 { 13 42 this.tupleof = params; 14 43 } 15 44 } 16 45 17 46 template DeriveCompare() 18 47 { 19 48 override: 20 - bool opEquals(Object rhs) 49 + bool opEquals(Object rhs) const 21 50 { 22 51 return tuple(this.tupleof) == tuple((cast(typeof(this))rhs).tupleof); 23 52 } 24 53 25 - int opCmp(Object rhs) 54 + int opCmp(Object rhs) const 26 55 { 27 56 return tuple(this.tupleof).opCmp(tuple((cast(typeof(this))rhs).tupleof)); 28 57 } 29 58 30 - hash_t toHash() 59 + hash_t toHash() const 31 60 { 32 61 hash_t v = 0; 33 62 foreach(mem; this.tupleof) { 34 63 v *= 11; 35 64 static if(__traits(compiles, v^=mem)) 36 65 v ^= mem; 37 66 else ................................................................................ 40 69 return v; 41 70 } 42 71 } 43 72 44 73 template DeriveShow() 45 74 { 46 75 override: 47 - string toString() 76 + string toString() const 48 77 { 49 78 string str = text(typeof(this).stringof, "("); 50 79 foreach(i,mem; this.tupleof) { 51 80 if(i) str ~= ", "; 52 81 str = text(str, this.tupleof[i].stringof[5..$], ":", mem); 53 82 } 54 83 return str ~ ")"; 55 84 } 56 85 }

Modified submission/README from [e299f78be5d1c45f] to [9ce063855f41ff05].

1 -Team "Dark Integers". 2 - 1 +Team: 2 + Dark Integers 3 3 Member: 4 - Kazuhiro Inaba (www.kmonos.net) 4 + Kazuhiro Inaba (www.kmonos.net / kiki@kmonos.net) 5 5 Language: 6 - D Programming Language (http://dlang.org) 6 + D Programming Language (dlang.org) 7 7 8 8 This submission for lightning division is not particulary interseting. 9 9 10 10 - Robot rushes to the nearest lambda (or the open lift) by breadth first search. 11 11 - Not at all taking into account the dynamics (falling rocks, floods). 12 12 - To mitigate the staticness, the robot avoids the '.' below '*' as much as 13 13 possible, so that it won't fall new rocks. ................................................................................ 18 18 trims the command history and inserts the 'A'bort at the optimal timing. 19 19 This is also used for SIGINT handling. 20 20 21 21 - gui.d is a windows GUI for the game, using DFL (http://github.com/Rayerd/dfl) 22 22 it is not compiled into the submitted routine. This is just a helper. 23 23 24 24 Stay tuned for the full submission, judges! 25 -