| ! ---------------------------------------------------------------------------- ! | |
| ! CheckOut.h | |
| ! original 1.0 May00 by Roger Firth (roger.firth@tesco.net) for Inform 6 | |
| ! | |
| ! ---------------------------------------------------------------------------- ! | |
| ! Installation: add the line: | |
| ! | |
| ! Include "CheckOut"; | |
| ! | |
| ! anywhere in your game AFTER the Include "Parser" statement. | |
| ! | |
| ! ---------------------------------------------------------------------------- ! | |
| ! Implements a debugging verb CHECKOUT which attempts to test all your rooms | |
| ! for asymmetric and one-way paths, on the basis that these /may/ represent | |
| ! errors in setting up the inter-room connections. | |
| ! | |
| ! Given two rooms Beach and Cliffs, the path between them is 'symmetric' if | |
| ! you can move (for example) NORTH from the Beach to get to the Cliffs, and | |
| ! then SOUTH from the Cliffs to return to the Beach. An 'asymmetric' path | |
| ! would be (for example) NORTH from the Beach to the Cliffs, while SOUTHEAST | |
| ! or WEST or DOWN (but not SOUTH) would take you back. Asymmetric paths are | |
| ! reported only where no symmetric path exists; if SOUTH, SOUTHEAST, WEST and | |
| ! DOWN all lead from the Cliffs to the Beach, no output is generated. | |
| ! | |
| ! A one-way path is (for example) NORTH from Beach to Cliffs, with no path | |
| ! returning to the Beach. | |
| ! | |
| ! All of this works by analysing the properties N_TO, NE_TO ... and DOOR_TO. | |
| ! Inform allows any of these to be a routine, but CheckOut has no way of | |
| ! determining what such a routine might return, and so treats it as though | |
| ! no exit was defined. Therefore, be prepared for some misleading reports. | |
| ! | |
| ! You can define a list of rooms to be skipped when analysing the paths; | |
| ! for example, a maze might deliberately contain many asymmetric paths which | |
| ! you don't wish to report on. Include a line like this immediately before | |
| ! you Include the file (don't forget the zero at the end of the list): | |
| ! | |
| ! Array SkipRoom --> room1 room2 ... roomN 0; | |
| ! | |
| ! ---------------------------------------------------------------------------- ! | |
| #ifdef DEBUG; message "Compiling CheckOut.h"; | |
| Constant ExitCount 12; | |
| Array ExitProp --> n_to ne_to e_to se_to u_to in_to | |
| s_to sw_to w_to nw_to d_to out_to; | |
| Array ExitName --> "North" "NorthEast" "East" "SouthEast" "Up" "In" | |
| "South" "SouthWest" "West" "NorthWest" "Down" "Out"; | |
| #ifndef SkipRoom; | |
| Array SkipRoom --> 1; | |
| #endif; | |
| [ CheckOutSub obj dest i k; | |
| objectloop(obj ofclass Object) { ! Loop through all Objects. | |
| if ((obj <= InformLibrary) || | |
| (obj == LibraryMessages) || ! Ignore system objects, | |
| (obj in 1) || ! those with a parent, | |
| (parent(obj)) || ! and those in SkipRoom, | |
| (OmitRoom(obj))) continue; ! leaving (mostly) rooms. | |
| for (i=0 : i<ExitCount : i++) { ! Test all possible exit properties. | |
| dest = GetExit(obj, i); | |
| if (dest == 0) continue; ! Not a (checkable) exit. | |
| if (dest == obj) { PrintExit(obj, i); print "itself^"; continue; } | |
| if (GetExit(dest, (i+(ExitCount/2))%ExitCount) == obj) continue; | |
| k = ScanExits(obj, dest); if (k < 0) continue; | |
| PrintExit(obj, i); print (name) dest, ": "; | |
| switch (k) { | |
| 0: print "no apparent return^"; | |
| 1: print "one asymmetric return^"; | |
| default: print (number) k, " asymmetric returns^"; | |
| } | |
| } ! end_FOR | |
| } ! end_OBJECTLOOP | |
| ]; | |
| [ ScanExits obj dest j k; | |
| k = 0; | |
| for (j=0 : j<ExitCount : j++ ) | |
| if (GetExit(dest, j) == obj) | |
| if (GetExit(obj, (j+(ExitCount/2))%ExitCount) == dest) return -1; else k++; | |
| return k; | |
| ]; | |
| [ GetExit obj i; | |
| switch (ExitType(obj, ExitProp-->i)) { | |
| 0: return 0; ! nowhere | |
| 1: return 0; ! routine | |
| 2: switch (ExitType(obj.(ExitProp-->i), door_to)) { | |
| 0: return 0; ! door to nowhere | |
| 1: return 0; ! door to routine | |
| 2: return 0; ! door to door! | |
| 3: return ((obj.(ExitProp-->i)).door_to); ! door to room | |
| } | |
| 3: return obj.(ExitProp-->i); ! room | |
| } | |
| ]; | |
| [ ExitType obj prop; | |
| if (obj == 0 || prop == 0) return 0; | |
| if (obj.#prop > 2 || obj.prop == NULL) return 0; | |
| switch(metaclass(obj.prop)) { | |
| nothing, Class, String: return 0; | |
| Routine: return 1; | |
| Object: if (obj.prop has door) return 2; else return 3; | |
| } | |
| ]; | |
| [ PrintExit obj i; | |
| print (name) obj, "->", (string) ExitName-->i, "->"; | |
| ]; | |
| [ OmitRoom obj i; | |
| i = 0; | |
| while (SkipRoom-->i) if (SkipRoom-->(i++) == obj) rtrue; | |
| rfalse; | |
| ]; | |
| Verb 'checkout' * -> CheckOut; | |
| #endif; | |
| ! ---------------------------------------------------------------------------- ! | |
Xet Storage Details
- Size:
- 4.99 kB
- Xet hash:
- fc31c932d09f7ad8c3fec9335cf068d645149e3795386be717e050871d63320c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.