| 1 | /* w_keys.c |
| 2 | * |
| 3 | * Micropolis, Unix Version. This game was released for the Unix platform |
| 4 | * in or about 1990 and has been modified for inclusion in the One Laptop |
| 5 | * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If |
| 6 | * you need assistance with this program, you may contact: |
| 7 | * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org. |
| 8 | * |
| 9 | * This program is free software: you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU General Public License as published by |
| 11 | * the Free Software Foundation, either version 3 of the License, or (at |
| 12 | * your option) any later version. |
| 13 | * |
| 14 | * This program is distributed in the hope that it will be useful, but |
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | * General Public License for more details. You should have received a |
| 18 | * copy of the GNU General Public License along with this program. If |
| 19 | * not, see <http://www.gnu.org/licenses/>. |
| 20 | * |
| 21 | * ADDITIONAL TERMS per GNU GPL Section 7 |
| 22 | * |
| 23 | * No trademark or publicity rights are granted. This license does NOT |
| 24 | * give you any right, title or interest in the trademark SimCity or any |
| 25 | * other Electronic Arts trademark. You may not distribute any |
| 26 | * modification of this program using the trademark SimCity or claim any |
| 27 | * affliation or association with Electronic Arts Inc. or its employees. |
| 28 | * |
| 29 | * Any propagation or conveyance of this program must include this |
| 30 | * copyright notice and these terms. |
| 31 | * |
| 32 | * If you convey this program (or any modifications of it) and assume |
| 33 | * contractual liability for the program to recipients of it, you agree |
| 34 | * to indemnify Electronic Arts for any liability that those contractual |
| 35 | * assumptions impose on Electronic Arts. |
| 36 | * |
| 37 | * You may not misrepresent the origins of this program; modified |
| 38 | * versions of the program must be marked as such and not identified as |
| 39 | * the original program. |
| 40 | * |
| 41 | * This disclaimer supplements the one included in the General Public |
| 42 | * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS |
| 43 | * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY |
| 44 | * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF |
| 45 | * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS |
| 46 | * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES, |
| 47 | * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, |
| 48 | * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY |
| 49 | * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING, |
| 50 | * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST |
| 51 | * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL |
| 52 | * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE |
| 53 | * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE |
| 54 | * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE |
| 55 | * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR |
| 56 | * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME |
| 57 | * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED |
| 58 | * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A |
| 59 | * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY |
| 60 | * NOT APPLY TO YOU. |
| 61 | */ |
| 62 | #include "sim.h" |
| 63 | |
| 64 | |
| 65 | static char LastKeys[5]; |
| 66 | |
| 67 | |
| 68 | /* TODO: |
| 69 | <n> new city |
| 70 | <l> load city |
| 71 | <s> save city |
| 72 | <q> quit |
| 73 | <a> autobulldoze |
| 74 | <0><1><2><3>... game speed |
| 75 | <m> map window |
| 76 | <g> graph window |
| 77 | <b> budget window |
| 78 | <e> evaluation window |
| 79 | */ |
| 80 | |
| 81 | |
| 82 | void |
| 83 | ResetLastKeys(void) |
| 84 | { |
| 85 | LastKeys[0] = ' '; |
| 86 | LastKeys[1] = ' '; |
| 87 | LastKeys[2] = ' '; |
| 88 | LastKeys[3] = ' '; |
| 89 | LastKeys[4] = '\0'; |
| 90 | PunishCnt = 0; |
| 91 | } |
| 92 | |
| 93 | |
| 94 | /* comefrom: processEvent */ |
| 95 | void |
| 96 | doKeyDown(SimView *view, short charCode) |
| 97 | { |
| 98 | LastKeys[0] = LastKeys[1]; |
| 99 | LastKeys[1] = LastKeys[2]; |
| 100 | LastKeys[2] = LastKeys[3]; |
| 101 | LastKeys[3] = tolower(charCode); |
| 102 | |
| 103 | if (strcmp(LastKeys, "fund") == 0) { |
| 104 | Spend(-10000); |
| 105 | PunishCnt++; /* punish for cheating */ |
| 106 | if (PunishCnt == 5) { |
| 107 | PunishCnt = 0; |
| 108 | MakeEarthquake(); |
| 109 | } |
| 110 | LastKeys[0] = '\0'; |
| 111 | } else if (strcmp(LastKeys, "fart") == 0) { |
| 112 | MakeSound("city", "Explosion-High"); |
| 113 | MakeSound("city", "Explosion-Low"); |
| 114 | MakeFire(); |
| 115 | MakeFlood(); |
| 116 | MakeTornado(); |
| 117 | MakeEarthquake(); |
| 118 | MakeMonster(); |
| 119 | LastKeys[0] = '\0'; |
| 120 | } else if (strcmp(LastKeys, "nuke") == 0) { |
| 121 | int i, j; |
| 122 | MakeSound("city", "Explosion-High"); |
| 123 | MakeSound("city", "Explosion-Low"); |
| 124 | for (i = 0; i < WORLD_X; i++) { |
| 125 | for (j = 0; j < WORLD_Y; j++) { |
| 126 | short tile = Map[i][j] & LOMASK; |
| 127 | if ((tile >= RUBBLE) && |
| 128 | ((tile < CHURCH - 4) || |
| 129 | (tile > CHURCH + 4))) { |
| 130 | if ((tile >= HBRIDGE && tile <= VBRIDGE) || |
| 131 | (tile >= BRWH && tile <= LTRFBASE + 1) || |
| 132 | (tile >= BRWV && tile <= BRWV + 2) || |
| 133 | (tile >= BRWXXX1 && tile <= BRWXXX1 + 2) || |
| 134 | (tile >= BRWXXX2 && tile <= BRWXXX2 + 2) || |
| 135 | (tile >= BRWXXX3 && tile <= BRWXXX3 + 2) || |
| 136 | (tile >= BRWXXX4 && tile <= BRWXXX4 + 2) || |
| 137 | (tile >= BRWXXX5 && tile <= BRWXXX5 + 2) || |
| 138 | (tile >= BRWXXX6 && tile <= BRWXXX6 + 2) || |
| 139 | (tile >= BRWXXX7 && tile <= BRWXXX7 + 2)) { |
| 140 | Map[i][j] = RIVER; |
| 141 | } else { |
| 142 | Map[i][j] = TINYEXP + ANIMBIT + BULLBIT + Rand(2); |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | } |
| 147 | LastKeys[0] = '\0'; |
| 148 | } else if (strcmp(LastKeys, "stop") == 0) { |
| 149 | heat_steps = 0; |
| 150 | LastKeys[0] = '\0'; |
| 151 | Kick(); |
| 152 | } else if (strcmp(LastKeys, "will") == 0) { |
| 153 | int i; |
| 154 | int n = 500; |
| 155 | for (i = 0; i < n; i++) { |
| 156 | int x1 = Rand(WORLD_X - 1); |
| 157 | int y1 = Rand(WORLD_Y - 1); |
| 158 | int x2 = Rand(WORLD_X - 1); |
| 159 | int y2 = Rand(WORLD_Y - 1); |
| 160 | short temp = |
| 161 | Map[x1][y1]; |
| 162 | Map[x1][y1] = |
| 163 | Map[x2][y2]; |
| 164 | Map[x2][y2] = |
| 165 | temp; |
| 166 | } |
| 167 | Kick(); |
| 168 | } else if (strcmp(LastKeys, "bobo") == 0) { |
| 169 | heat_steps = 1; |
| 170 | heat_flow = -1; |
| 171 | heat_rule = 0; |
| 172 | LastKeys[0] = '\0'; |
| 173 | Kick(); |
| 174 | } else if (strcmp(LastKeys, "boss") == 0) { |
| 175 | heat_steps = 1; |
| 176 | heat_flow = 1; |
| 177 | heat_rule = 0; |
| 178 | LastKeys[0] = '\0'; |
| 179 | Kick(); |
| 180 | } else if (strcmp(LastKeys, "mack") == 0) { |
| 181 | heat_steps = 1; |
| 182 | heat_flow = 0; |
| 183 | heat_rule = 0; |
| 184 | LastKeys[0] = '\0'; |
| 185 | Kick(); |
| 186 | } else if (strcmp(LastKeys, "donh") == 0) { |
| 187 | heat_steps = 1; |
| 188 | heat_flow = -1; |
| 189 | heat_rule = 1; |
| 190 | LastKeys[0] = '\0'; |
| 191 | Kick(); |
| 192 | } else if (strcmp(LastKeys, "patb") == 0) { |
| 193 | heat_steps = 1; |
| 194 | heat_flow = Rand(40) - 20; |
| 195 | heat_rule = 0; |
| 196 | LastKeys[0] = '\0'; |
| 197 | Kick(); |
| 198 | } else if (strcmp(LastKeys, "lucb") == 0) { |
| 199 | heat_steps = 1; |
| 200 | heat_flow = Rand(1000) - 500; |
| 201 | heat_rule = 0; |
| 202 | LastKeys[0] = '\0'; |
| 203 | Kick(); |
| 204 | } else if (strcmp(LastKeys, "olpc") == 0) { |
| 205 | Spend(-1000000); |
| 206 | } |
| 207 | |
| 208 | switch (charCode) { |
| 209 | |
| 210 | case 'X': |
| 211 | case 'x': { |
| 212 | short s = view->tool_state; |
| 213 | if (++s > lastState) { |
| 214 | s = firstState; |
| 215 | } |
| 216 | setWandState(view, s); |
| 217 | break; |
| 218 | } |
| 219 | |
| 220 | case 'Z': |
| 221 | case 'z': { |
| 222 | short s = view->tool_state; |
| 223 | if (--s < firstState) { |
| 224 | s = lastState; |
| 225 | } |
| 226 | setWandState(view, s); |
| 227 | break; |
| 228 | } |
| 229 | |
| 230 | /***** shift wand state to bull dozer *****/ |
| 231 | case 'B': |
| 232 | case 'b': |
| 233 | case 'B'-'@': { |
| 234 | if (view->tool_state_save == -1) { |
| 235 | view->tool_state_save = view->tool_state; |
| 236 | } |
| 237 | setWandState(view, dozeState); |
| 238 | break; |
| 239 | } |
| 240 | |
| 241 | /***** shift wand state to roads *****/ |
| 242 | case 'R': |
| 243 | case 'r': |
| 244 | case 'R'-'@': { |
| 245 | if (view->tool_state_save == -1) { |
| 246 | view->tool_state_save = view->tool_state; |
| 247 | } |
| 248 | setWandState(view, roadState); |
| 249 | break; |
| 250 | } |
| 251 | |
| 252 | /***** shift wand state to power *****/ |
| 253 | case 'P': |
| 254 | case 'p': |
| 255 | case 'P'-'@': { |
| 256 | if (view->tool_state_save == -1) { |
| 257 | view->tool_state_save = view->tool_state; |
| 258 | } |
| 259 | setWandState(view, wireState); |
| 260 | break; |
| 261 | } |
| 262 | |
| 263 | /***** shift wand state to transit *****/ |
| 264 | case 'T': |
| 265 | case 't': |
| 266 | case 'T'-'@': { |
| 267 | if (view->tool_state_save == -1) { |
| 268 | view->tool_state_save = view->tool_state; |
| 269 | } |
| 270 | setWandState(view, rrState); |
| 271 | break; |
| 272 | } |
| 273 | |
| 274 | #if 0 |
| 275 | /***** shift wand state to query *****/ |
| 276 | case 'Q': |
| 277 | case 'q': |
| 278 | case 'Q'-'@': { |
| 279 | if (view->tool_state_save == -1) |
| 280 | view->tool_state_save = view->tool_state; |
| 281 | setWandState(view, queryState); |
| 282 | break; |
| 283 | } |
| 284 | #endif |
| 285 | |
| 286 | case 27: { |
| 287 | SoundOff(); |
| 288 | break; |
| 289 | } |
| 290 | |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | |
| 295 | /* comefrom: processEvent */ |
| 296 | void |
| 297 | doKeyUp(SimView *view, short charCode) |
| 298 | { |
| 299 | switch(charCode) { |
| 300 | |
| 301 | case 'b': |
| 302 | case 'B': |
| 303 | case 'B'-'@': |
| 304 | case 'R': |
| 305 | case 'r': |
| 306 | case 'R'-'@': |
| 307 | case 'P': |
| 308 | case 'p': |
| 309 | case 'P'-'@': |
| 310 | case 'T': |
| 311 | case 't': |
| 312 | case 'T'-'@': |
| 313 | case 'q': |
| 314 | case 'Q': |
| 315 | case 'Q'-'@': { |
| 316 | if (view->tool_state_save != -1) { |
| 317 | setWandState(view, view->tool_state_save); |
| 318 | } |
| 319 | view->tool_state_save = -1; |
| 320 | break; |
| 321 | } |
| 322 | |
| 323 | default: { |
| 324 | break; |
| 325 | } |
| 326 | |
| 327 | } |
| 328 | } |