1: 2: 3: logic 4: { 5: /* Play area size */ 6: int boardWidth {40} 7: int boardHeight {40} 8: 9: /* Tiles on play area */ 10: int TILE_EMPTY {0} 11: int TILE_EARTH {1} 12: int TILE_GOLD {2} 13: int TILE_PLAYER {3} 14: int TILE_ROCK {8} 15: int TILE_WALL {9} 16: 17: /* bit 3 indicates whether the player can "move into" a tile */ 18: int TILE_SOLID_FLAG {8} 19: 20: /* Write your level here */ 21: array board 22: { 23: 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 24: 9, 3, 9, 1, 1, 9, 1, 1, 1, 8, 1, 1, 8, 1, 8, 1, 8, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25: 9, 1, 9, 2, 1, 9, 2, 9, 8, 1, 1, 8, 0, 0, 8, 1, 1, 9, 1, 1, 1, 1, 9, 0, 1, 1, 1, 9, 1, 1, 1, 1, 0, 0, 1, 1, 1, 9, 1, 1, 26: 9, 1, 9, 9, 8, 9, 9, 9, 1, 8, 1, 2, 8, 8, 8, 2, 8, 9, 1, 1, 1, 1, 9, 8, 1, 1, 1, 9, 1, 1, 1, 1, 0, 8, 1, 1, 1, 9, 1, 1, 27: 9, 1, 1, 1, 1, 1, 1, 9, 8, 2, 1, 8, 1, 2, 8, 8, 8, 9, 9, 1, 1, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 28: 9, 9, 9, 9, 9, 1, 9, 9, 9, 2, 8, 1, 1, 8, 2, 8, 1, 8, 9, 1, 1, 1, 9, 8, 1, 8, 1, 1, 9, 1, 1, 1, 1, 8, 1, 8, 1, 1, 9, 1, 29: 9, 8, 2, 1, 9, 2, 9, 8, 9, 8, 1, 1, 8, 1, 1, 1, 8, 2, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 30: 9, 1, 8, 2, 8, 2, 1, 2, 9, 1, 8, 1, 2, 2, 8, 2, 8, 2, 9, 1, 1, 1, 9, 0, 1, 0, 1, 0, 9, 1, 1, 1, 1, 0, 1, 0, 1, 0, 9, 1, 31: 9, 8, 1, 1, 1, 1, 1, 0, 9, 2, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 32: 9, 1, 1, 9, 9, 9, 1, 0, 9, 9, 9, 9, 9, 1, 8, 1, 8, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 33: 9, 1, 1, 1, 1, 9, 9, 0, 9, 8, 8, 2, 9, 8, 8, 1, 1, 8, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 34: 9, 1, 1, 1, 1, 1, 9, 0, 9, 8, 8, 8, 9, 1, 1, 8, 1, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35: 9, 1, 1, 0, 0, 1, 9, 0, 9, 8, 8, 2, 9, 0, 0, 1, 1, 1, 9, 1, 1, 1, 9, 0, 0, 1, 1, 1, 9, 1, 1, 1, 1, 0, 0, 1, 1, 1, 9, 1, 36: 9, 9, 9, 0, 8, 1, 9, 9, 9, 8, 8, 8, 9, 8, 8, 8, 1, 8, 8, 1, 1, 1, 9, 0, 8, 1, 1, 1, 9, 1, 1, 1, 1, 0, 8, 1, 1, 1, 9, 1, 37: 9, 9, 1, 1, 1, 1, 1, 9, 9, 8, 8, 2, 9, 2, 1, 1, 1, 1, 8, 1, 1, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 38: 9, 1, 1, 8, 9, 8, 1, 9, 9, 8, 8, 8, 9, 8, 1, 8, 1, 1, 9, 1, 1, 1, 9, 8, 1, 8, 1, 1, 9, 1, 1, 1, 1, 8, 1, 8, 1, 1, 9, 1, 39: 9, 1, 1, 1, 9, 1, 1, 1, 9, 8, 8, 1, 9, 9, 9, 9, 9, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 40: 9, 1, 1, 2, 9, 2, 1, 2, 9, 8, 1, 1, 0, 2, 0, 2, 9, 2, 9, 1, 1, 1, 9, 0, 1, 0, 1, 0, 9, 1, 1, 1, 1, 0, 1, 0, 1, 0, 9, 1, 41: 9, 1, 9, 1, 9, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 9, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 42: 9, 1, 9, 1, 9, 1, 1, 1, 1, 9, 0, 0, 0, 0, 0, 0, 9, 1, 9, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 43: 9, 1, 9, 1, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 9, 1, 9, 0, 8, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 44: 9, 1, 9, 1, 1, 1, 1, 1, 1, 1, 9, 9, 0, 0, 0, 0, 1, 1, 1, 1, 9, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45: 9, 1, 9, 0, 0, 1, 1, 1, 9, 1, 1, 9, 0, 0, 9, 9, 9, 9, 0, 0, 9, 1, 9, 0, 0, 1, 1, 1, 9, 1, 1, 1, 1, 0, 0, 1, 1, 1, 9, 1, 46: 9, 1, 9, 0, 8, 1, 1, 1, 9, 1, 1, 9, 9, 0, 9, 1, 8, 9, 9, 1, 9, 1, 9, 0, 8, 1, 1, 1, 9, 1, 1, 1, 1, 0, 8, 1, 1, 1, 9, 1, 47: 9, 1, 9, 9, 9, 9, 9, 1, 9, 1, 1, 1, 1, 9, 9, 1, 1, 1, 9, 1, 9, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 48: 9, 1, 1, 8, 1, 8, 9, 1, 9, 1, 1, 1, 1, 8, 1, 8, 1, 1, 9, 1, 9, 1, 9, 8, 1, 8, 1, 1, 9, 1, 1, 1, 1, 8, 1, 8, 1, 1, 9, 1, 49: 9, 8, 1, 1, 1, 1, 9, 1, 9, 1, 1, 1, 1, 1, 8, 1, 8, 1, 9, 0, 9, 1, 9, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 50: 9, 8, 8, 2, 1, 2, 9, 2, 9, 9, 9, 9, 9, 2, 1, 2, 8, 2, 9, 0, 9, 1, 9, 9, 9, 9, 1, 0, 9, 1, 1, 1, 1, 0, 1, 0, 1, 0, 9, 1, 51: 9, 8, 1, 1, 1, 1, 9, 1, 8, 8, 1, 1, 9, 1, 1, 1, 8, 1, 9, 1, 8, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 52: 9, 2, 1, 1, 1, 1, 9, 1, 9, 9, 9, 1, 9, 9, 8, 8, 9, 1, 9, 1, 9, 9, 9, 9, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 53: 9, 9, 2, 1, 1, 1, 9, 1, 9, 2, 9, 1, 9, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 54: 9, 2, 9, 1, 1, 1, 9, 1, 9, 2, 9, 1, 9, 1, 1, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 55: 9, 2, 2, 9, 0, 1, 9, 1, 9, 2, 9, 1, 1, 0, 0, 1, 1, 1, 9, 9, 9, 9, 1, 9, 9, 9, 1, 1, 9, 1, 1, 1, 1, 0, 0, 1, 1, 1, 9, 1, 56: 9, 2, 2, 2, 9, 1, 1, 1, 9, 1, 9, 1, 1, 0, 8, 1, 1, 1, 9, 8, 8, 9, 1, 9, 8, 1, 1, 1, 9, 1, 1, 1, 1, 0, 8, 1, 1, 1, 9, 1, 57: 9, 1, 1, 1, 9, 9, 9, 1, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 9, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 58: 9, 1, 1, 8, 1, 8, 1, 1, 8, 1, 1, 1, 1, 8, 1, 8, 1, 1, 9, 8, 8, 9, 1, 9, 1, 8, 1, 1, 9, 1, 1, 1, 1, 8, 1, 8, 1, 1, 9, 1, 59: 9, 1, 1, 1, 1, 1, 9, 9, 9, 1, 2, 2, 1, 1, 1, 1, 1, 1, 9, 8, 8, 9, 1, 9, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 1, 60: 9, 1, 1, 2, 1, 2, 1, 2, 9, 1, 2, 2, 1, 2, 1, 2, 1, 2, 9, 8, 8, 9, 1, 9, 1, 0, 1, 0, 9, 1, 1, 1, 1, 0, 1, 0, 1, 0, 9, 1, 61: 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62: 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 63: } 64: 65: /* Player's start position */ 66: int playerX {1} 67: int playerY {1} 68: 69: 70: 71: 72: /* Gold remaining */ 73: int goldRemaining {58} 74: 75: /* 76: * Enumerate possible moves a player can make 77: * (none - left - right - up - down ) 78: */ 79: array xMoves { 0, -1, 1, 0, 0 } 80: array yMoves { 0, 0, 0, -1, 1 } 81: 82: /** 83: * Display viewport is 10x10 of 40x40 84: */ 85: int displayX {0} 86: int displayY {0} 87: int displayWidth {10} 88: int displayHeight {10} 89: 90: /* Is the player still alive? */ 91: int dead {0} 92: 93: /* Internal variable */ 94: int y2 {0} 95: 96: /* Decide which of the five possible player moves are legal */ 97: for p (0..4) 98: { 99: /* Trivial player move - allow any move into a non-solid tile */ 100: when 101: { 102: ((playerX + xMoves[p]) >= 0) 103: and ((playerX + xMoves[p]) < boardWidth) 104: and ((playerY + yMoves[p]) >= 0) 105: and ((playerY + yMoves[p]) < boardHeight) 106: and ((board[ (playerX + xMoves[p]) + ((playerY + yMoves[p]) * boardWidth ) ] & TILE_SOLID_FLAG) == 0) 107: and ( dead == 0 ) 108: } 109: allow 110: { 111: board[ playerX + (playerY * boardWidth ) ] = TILE_EMPTY; 112: playerX = (playerX + xMoves[p]); 113: playerY = (playerY + yMoves[p]); 114: board[ playerX + (playerY * boardWidth ) ] = TILE_PLAYER; 115: } 116: label 117: { 118: "Player dx=" xMoves[p] " dy=" yMoves[p] "." 119: } 120: 121: /* Handle player pushing rocks left and right (into empty space only!) */ 122: when 123: { 124: ((playerX + (xMoves[p]*2)) >= 0) 125: and ((playerX + (xMoves[p]*2)) < boardWidth ) 126: and ( yMoves[p] == 0 ) 127: and ( board[ (playerX + xMoves[p] ) + (playerY * boardWidth ) ] == TILE_ROCK ) 128: and ( board[ (playerX + (xMoves[p] * 2)) + (playerY * boardWidth ) ] == TILE_EMPTY ) 129: and ( dead == 0 ) 130: } 131: allow 132: { 133: 134: board[ playerX + (playerY * boardWidth ) ] = TILE_EMPTY; 135: board[ (playerX + (xMoves[p] * 2)) + (playerY * boardWidth ) ] = TILE_ROCK; 136: playerX = (playerX + xMoves[p]); 137: board[ playerX + (playerY * boardWidth ) ] = TILE_PLAYER; 138: } 139: label 140: { 141: "Player dx=" xMoves[p] " dy=" yMoves[p] "." 142: } 143: 144: /* Count the remaining Gold */ 145: when 146: { 147: ((playerX + xMoves[p]) >= 0) 148: and ((playerX + xMoves[p]) < boardWidth) 149: and ((playerY + yMoves[p]) >= 0) 150: and ((playerY + yMoves[p]) < boardHeight) 151: and (board[ (playerX + xMoves[p]) + ((playerY + yMoves[p]) * boardWidth ) ] == TILE_GOLD) 152: and ( dead == 0 ) 153: and ( goldRemaining > 0 ) 154: } 155: allow 156: { 157: goldRemaining = goldRemaining - 1; 158: } 159: label 160: { 161: "Player dx=" xMoves[p] " dy=" yMoves[p] "." 162: } 163: 164: 165: /* Handle horizontal view port scrolling. This is fiddly as it playerX is going to be 166: * different when the allow block is calculated! 167: */ 168: when 169: { 170: ( ( playerX + xMoves[p] - (displayWidth/2) ) >= 0 ) 171: and ( ( playerX + xMoves[p] - (displayWidth/2) ) <= (boardWidth - displayWidth ) ) 172: } 173: allow 174: { 175: displayX = ( playerX - (displayWidth/2) ); 176: } 177: label 178: { 179: "Player dx=" xMoves[p] " dy=" yMoves[p] "." 180: } 181: 182: /* Handle vertical view port scrolling. As horizontal case... */ 183: when 184: { 185: ( ( playerY + yMoves[p] - (displayHeight/2) ) >= 0 ) 186: and ( ( playerY + yMoves[p] - (displayHeight/2) ) <= (boardHeight - displayHeight ) ) 187: } 188: allow 189: { 190: displayY = ( playerY - (displayHeight/2) ); 191: } 192: label 193: { 194: "Player dx=" xMoves[p] " dy=" yMoves[p] "." 195: } 196: 197: when 198: { 199: goldRemaining > 0 200: } 201: allow 202: { 203: /* Handle falling rocks! We need to find them first hence the for/for nest... 204: * This is technically O(n^2) with the size of the board. I have cheated and 205: * only move rocks the player can actually see on screen :). Ideally, I would 206: * track the individual rocks O(n) with number of rocks 207: */ 208: for y ( 0 .. (boardHeight - 1 ) ) 209: { 210: y2 = (boardHeight - 1 ) - y; 211: for x ( displayX .. (displayX + displayWidth - 1) ) 212: { 213: /** Is this a rock? */ 214: if ( board[ x + ( y2 * boardWidth ) ] == TILE_ROCK ) 215: { 216: /* Is the player about to get splatted? */ 217: if 218: ( 219: ( y2 < (boardHeight - 2) ) 220: and ( board[ x + ( ( y2 + 1 ) * boardWidth ) ] == TILE_EMPTY ) 221: and ( board[ x + ( ( y2 + 2 ) * boardWidth ) ] == TILE_PLAYER ) 222: ) 223: { 224: dead = 1; 225: } 226: 227: 228: /* This is the simple rock falling down case... */ 229: if 230: ( 231: ( board[ x + ( ( y2 + 1 ) * boardWidth ) ] == TILE_EMPTY ) 232: ) 233: { 234: board[ x + ( ( y2 ) * boardWidth ) ] = TILE_EMPTY; 235: board[ x + ( ( y2 + 1 ) * boardWidth ) ] = TILE_ROCK; 236: } 237: 238: /* Handle rocks that are going to fall left to a space to the bottom-left */ 239: if 240: ( 241: ( x != 0 ) 242: and ( board[ x + ( y2 * boardWidth ) ] == TILE_ROCK ) 243: and ( board[ x + ( ( y2 + 1 ) * boardWidth ) ] != TILE_EMPTY ) 244: and ( board[ x - 1 + ( ( y2 ) * boardWidth ) ] == TILE_EMPTY ) 245: and ( board[ x - 1 + ( ( y2 + 1 ) * boardWidth ) ] == TILE_EMPTY ) 246: ) 247: { 248: board[ x + ( ( y2 ) * boardWidth ) ] = TILE_EMPTY; 249: board[ x - 1 + ( ( y2 + 1 ) * boardWidth ) ] = TILE_ROCK; 250: } 251: 252: /* Handle rocks that are going to fall right to a space to the bottom-right */ 253: if 254: ( 255: ( x != (boardWidth - 1) ) 256: and ( board[ x + ( y2 * boardWidth ) ] == TILE_ROCK ) 257: and ( board[ x + ( ( y2 + 1 ) * boardWidth ) ] != TILE_EMPTY ) 258: and ( board[ x + 1 + ( ( y2 ) * boardWidth ) ] == TILE_EMPTY ) 259: and ( board[ x + 1 + ( ( y2 + 1 ) * boardWidth ) ] == TILE_EMPTY ) 260: ) 261: { 262: board[ x + ( y2 * boardWidth ) ] = TILE_EMPTY; 263: board[ x + 1 + ( (y2 + 1) * boardWidth ) ] = TILE_ROCK; 264: } 265: } 266: } 267: 268: 269: 270: 271: } 272: } 273: label 274: { 275: "Player dx=" xMoves[p] " dy=" yMoves[p] "." 276: } 277: } 278: 279: } 280: 281: display 282: { 283: /* Icons to display */ 284: stringtable items 285: { 286: " ", 287: "~", 288: "$", 289: "&", 290: "", "", "", "" 291: "*", 292: 293: "#" 294: } 295: 296: 297: /* Display the game state */ 298: stringtable gameState 299: { 300: "Rock on...", 301: "Game Over" 302: } 303: 304: /* Title */ 305: box 306: { 307: content { "Gold Digger!" } 308: } 309: newline 310: /* Play area */ 311: for y ( 0 .. ( displayWidth - 1 ) ) 312: { 313: for x ( 0 .. ( displayHeight - 1 ) ) 314: { 315: box 316: { 317: width { 2em } 318: 319: height { 2em } 320: border { 1px solid black } 321: 322: /* Choose colour. TODO - figure out how to get an array to work! */ 323: if ( board[ ( x + displayX ) + ( ( y + displayY ) * boardWidth )] == TILE_EARTH ) 324: { 325: background { #999 } 326: } 327: if ( board[ ( x + displayX ) + ( ( y + displayY ) * boardWidth )] == TILE_GOLD ) 328: { 329: background { #F0F } 330: } 331: if ( board[ ( x + displayX ) + ( ( y + displayY ) * boardWidth )] == TILE_ROCK ) 332: { 333: background { #777 } 334: } 335: if ( board[ ( x + displayX ) + ( ( y + displayY ) * boardWidth )] == TILE_WALL ) 336: { 337: background { #555 } 338: } 339: /* Display icon */ 340: content { items[ board[ ( x + displayX ) + ( ( y + displayY ) * boardWidth )] ] } 341: } 342: } 343: newline 344: } 345: newline 346: newline 347: /* Display direction options */ 348: box 349: { 350: width { 2em } 351: height { 2em } 352: border { 1px solid black } 353: content { " " } 354: bind_action { "Player dx=0 dy=0." } 355: } 356: box 357: { 358: 359: width { 2em } 360: 361: 362: 363: height { 2em } 364: border { 1px solid black } 365: content { "Up" } 366: bind_action { "Player dx=0 dy=-1." } 367: } 368: box 369: { 370: width { 2em } 371: height { 2em } 372: border { 1px solid black } 373: content { "Wait" } 374: bind_action { "Player dx=0 dy=0." } 375: } 376: newline 377: box 378: { 379: width { 2em } 380: height { 2em } 381: border { 1px solid black } 382: content { "Left" } 383: bind_action { "Player dx=-1 dy=0." } 384: } 385: box 386: { 387: width { 2em } 388: height { 2em } 389: border { 1px solid black } 390: content { "Down" } 391: bind_action { "Player dx=0 dy=1." } 392: } 393: box 394: { 395: width { 2em } 396: height { 2em } 397: border { 1px solid black } 398: content { "Right" } 399: bind_action { "Player dx=1 dy=0." } 400: } 401: newline 402: /* Show the player state */ 403: box 404: { 405: content { gameState[ dead ] } 406: } 407: box 408: { 409: content { goldRemaining } 410: } 411: } 412: