Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
realm.cpp
00001 /* 00002 Copyright (C) 2014 Frank Duignan 00003 00004 This program is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU General Public License 00006 as published by the Free Software Foundation; either version 2 00007 of the License, or (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 #include "mbed.h" 00019 #include "realm.h" 00020 #include "serial.h" 00021 // Find types: h(ealth),s(trength),m(agic),g(old),w(eapon) 00022 const char FindTypes[]={'h','s','m','g','w'}; 00023 00024 00025 // The following arrays define the bad guys and 00026 // their battle properies - ordering matters! 00027 // Baddie types : O(gre),T(roll),D(ragon),H(ag) 00028 const char Baddies[]={'O','T','D','H'}; 00029 // The following is 4 sets of 4 damage types 00030 const byte WeaponDamage[]={10,10,5,25,10,10,5,25,10,15,5,15,5,5,2,10}; 00031 #define ICE_SPELL_COST 10 00032 #define FIRE_SPELL_COST 20 00033 #define LIGHTNING_SPELL_COST 30 00034 const byte FreezeSpellDamage[]={10,20,5,0}; 00035 const byte FireSpellDamage[]={20,10,5,0}; 00036 const byte LightningSpellDamage[]={15,10,25,0}; 00037 const byte BadGuyDamage[]={10,10,15,5}; 00038 int GameStarted = 0; 00039 tPlayer thePlayer; 00040 tRealm theRealm; 00041 void delay(int len); 00042 00043 void delay(int len) 00044 { 00045 wait(len/1000); 00046 } 00047 void runGame(void) 00048 { 00049 char ch; 00050 00051 printString("MicroRealms on mbed."); 00052 showHelp(); 00053 while(GameStarted == 0) 00054 { 00055 00056 showGameMessage("Press S to start a new game"); 00057 ch = getUserInput(); 00058 00059 if ( (ch == 'S') || (ch == 's') ) 00060 GameStarted = 1; 00061 } 00062 00063 initRealm(&theRealm); 00064 initPlayer(&thePlayer,&theRealm); 00065 showPlayer(&thePlayer); 00066 showRealm(&theRealm,&thePlayer); 00067 showGameMessage("Press H for help"); 00068 00069 while (1) 00070 { 00071 ch = getUserInput(); 00072 ch = ch | 32; // enforce lower case 00073 switch (ch) { 00074 case 'h' : { 00075 showHelp(); 00076 break; 00077 } 00078 case 'n' : { 00079 showGameMessage("North"); 00080 step('n',&thePlayer,&theRealm); 00081 break; 00082 } 00083 case 's' : { 00084 showGameMessage("South"); 00085 step('s',&thePlayer,&theRealm); 00086 break; 00087 00088 } 00089 case 'e' : { 00090 showGameMessage("East"); 00091 step('e',&thePlayer,&theRealm); 00092 break; 00093 } 00094 case 'w' : { 00095 showGameMessage("West"); 00096 step('w',&thePlayer,&theRealm); 00097 break; 00098 } 00099 case '#' : { 00100 if (thePlayer.wealth) 00101 { 00102 showRealm(&theRealm,&thePlayer); 00103 thePlayer.wealth--; 00104 } 00105 else 00106 showGameMessage("No gold!"); 00107 break; 00108 } 00109 case 'p' : { 00110 showPlayer(&thePlayer); 00111 break; 00112 } 00113 } // end switch 00114 } // end while 00115 } 00116 void step(char Direction,tPlayer *Player,tRealm *Realm) 00117 { 00118 int new_x, new_y; 00119 new_x = Player->x; 00120 new_y = Player->y; 00121 byte AreaContents; 00122 switch (Direction) { 00123 case 'n' : 00124 { 00125 if (new_y > 0) 00126 new_y--; 00127 break; 00128 } 00129 case 's' : 00130 { 00131 if (new_y < MAP_HEIGHT-1) 00132 new_y++; 00133 break; 00134 } 00135 case 'e' : 00136 { 00137 if (new_x < MAP_WIDTH-1) 00138 new_x++; 00139 break; 00140 } 00141 case 'w' : 00142 { 00143 if (new_x > 0) 00144 new_x--; 00145 break; 00146 } 00147 } 00148 AreaContents = Realm->map[new_y][new_x]; 00149 if ( AreaContents == '*') 00150 { 00151 showGameMessage("A rock blocks your path."); 00152 return; 00153 } 00154 Player->x = new_x; 00155 Player->y = new_y; 00156 int Consumed = 0; 00157 switch (AreaContents) 00158 { 00159 00160 // const char Baddies[]={'O','T','B','H'}; 00161 case 'O' :{ 00162 showGameMessage("A smelly green Ogre appears before you"); 00163 Consumed = doChallenge(Player,0); 00164 break; 00165 } 00166 case 'T' :{ 00167 showGameMessage("An evil troll challenges you"); 00168 Consumed = doChallenge(Player,1); 00169 break; 00170 } 00171 case 'D' :{ 00172 showGameMessage("A smouldering Dragon blocks your way !"); 00173 Consumed = doChallenge(Player,2); 00174 break; 00175 } 00176 case 'H' :{ 00177 showGameMessage("A withered hag cackles at you wickedly"); 00178 Consumed = doChallenge(Player,3); 00179 break; 00180 } 00181 case 'h' :{ 00182 showGameMessage("You find an elixer of health"); 00183 setHealth(Player,Player->health+10); 00184 Consumed = 1; 00185 break; 00186 00187 } 00188 case 's' :{ 00189 showGameMessage("You find a potion of strength"); 00190 Consumed = 1; 00191 setStrength(Player,Player->strength+1); 00192 break; 00193 } 00194 case 'g' :{ 00195 showGameMessage("You find a shiny golden nugget"); 00196 Player->wealth++; 00197 Consumed = 1; 00198 break; 00199 } 00200 case 'm' :{ 00201 showGameMessage("You find a magic charm"); 00202 Player->magic++; 00203 Consumed = 1; 00204 break; 00205 } 00206 case 'w' :{ 00207 Consumed = addWeapon(Player,random(MAX_WEAPONS-1)+1); 00208 showPlayer(Player); 00209 break; 00210 } 00211 case 'X' : { 00212 // Player landed on the exit 00213 printString("A door! You exit into a new realm"); 00214 setHealth(Player,100); // maximize health 00215 initRealm(&theRealm); 00216 showRealm(&theRealm,Player); 00217 } 00218 } 00219 if (Consumed) 00220 Realm->map[new_y][new_x] = '.'; // remove any item that was found 00221 } 00222 int doChallenge(tPlayer *Player,int BadGuyIndex) 00223 { 00224 char ch; 00225 char Damage; 00226 const byte *dmg; 00227 int BadGuyHealth = 100; 00228 printString("Press F to fight"); 00229 ch = getUserInput() | 32; // get user input and force lower case 00230 if (ch == 'f') 00231 { 00232 printString("Choose action"); 00233 while ( (Player->health > 0) && (BadGuyHealth > 0) ) 00234 { 00235 // Player takes turn first 00236 if (Player->magic > ICE_SPELL_COST) 00237 printString("(I)CE spell"); 00238 if (Player->magic > FIRE_SPELL_COST) 00239 printString("(F)ire spell"); 00240 if (Player->magic > LIGHTNING_SPELL_COST) 00241 printString("(L)ightning spell"); 00242 if (Player->Weapon1) 00243 { 00244 eputs("(1)Use "); 00245 printString(getWeaponName(Player->Weapon1)); 00246 } 00247 if (Player->Weapon2) 00248 { 00249 eputs("(2)Use "); 00250 printString(getWeaponName(Player->Weapon2)); 00251 } 00252 printString("(P)unch"); 00253 ch = getUserInput(); 00254 switch (ch) 00255 { 00256 case 'i': 00257 case 'I': 00258 { 00259 printString("FREEZE!"); 00260 Player->magic -= ICE_SPELL_COST; 00261 BadGuyHealth -= FreezeSpellDamage[BadGuyIndex]+random(10); 00262 zap(); 00263 break; 00264 } 00265 case 'f': 00266 case 'F': 00267 { 00268 printString("BURN!"); 00269 Player->magic -= FIRE_SPELL_COST; 00270 BadGuyHealth -= FireSpellDamage[BadGuyIndex]+random(10); 00271 zap(); 00272 break; 00273 } 00274 case 'l': 00275 case 'L': 00276 { 00277 printString("ZAP!"); 00278 Player->magic -= LIGHTNING_SPELL_COST; 00279 BadGuyHealth -= LightningSpellDamage[BadGuyIndex]+random(10); 00280 zap(); 00281 break; 00282 } 00283 case '1': 00284 { 00285 dmg = WeaponDamage+(Player->Weapon1<<2)+BadGuyIndex; 00286 printString("Take that!"); 00287 BadGuyHealth -= *dmg + random(Player->strength); 00288 setStrength(Player,Player->strength-1); 00289 break; 00290 } 00291 case '2': 00292 { 00293 dmg = WeaponDamage+(Player->Weapon2<<2)+BadGuyIndex; 00294 printString("Take that!"); 00295 BadGuyHealth -= *dmg + random(Player->strength); 00296 setStrength(Player,Player->strength-1); 00297 break; 00298 } 00299 case 'p': 00300 case 'P': 00301 { 00302 printString("Thump!"); 00303 BadGuyHealth -= 1+random(Player->strength); 00304 setStrength(Player,Player->strength-1); 00305 break; 00306 } 00307 default: { 00308 printString("You fumble. Uh oh"); 00309 } 00310 } 00311 // Bad guy then gets a go 00312 00313 if (BadGuyHealth < 0) 00314 BadGuyHealth = 0; 00315 Damage = BadGuyDamage[BadGuyIndex]+random(5); 00316 setHealth(Player,Player->health - Damage); 00317 eputs("Health: you "); printHex(Player->health); 00318 eputs(", them " );printHex(BadGuyHealth); 00319 eputs("\r\n"); 00320 } 00321 if (Player->health == 0) 00322 { // You died 00323 printString("You are dead. Press Reset to restart"); 00324 while(1); 00325 } 00326 else 00327 { // You won! 00328 Player->wealth = 50 + random(50); 00329 showGameMessage("You win! Their gold is yours"); 00330 return 1; 00331 } 00332 00333 } 00334 else 00335 { 00336 showGameMessage("Our 'hero' chickens out"); 00337 return 0; 00338 } 00339 } 00340 int addWeapon(tPlayer *Player, int Weapon) 00341 { 00342 char c; 00343 eputs("You stumble upon "); 00344 switch (Weapon) 00345 { 00346 case 1: 00347 { 00348 printString("a mighty axe"); 00349 break; 00350 } 00351 case 2: 00352 { 00353 printString("a sword with mystical runes"); 00354 break; 00355 } 00356 case 3: 00357 { 00358 printString("a bloody flail"); 00359 break; 00360 } 00361 default: 00362 printHex(Weapon); 00363 } 00364 if ( (Player->Weapon1) && (Player->Weapon2) ) 00365 { 00366 // The player has two weapons already. 00367 showPlayer(Player); 00368 printString("You already have two weapons"); 00369 printString("(1) drop Weapon1, (2) for Weapon2, (0) skip"); 00370 c = getUserInput(); 00371 switch(c) 00372 { 00373 case '0':{ 00374 return 0; // don't pick up 00375 } 00376 case '1':{ 00377 Player->Weapon1 = Weapon; 00378 break; 00379 } 00380 case '2':{ 00381 Player->Weapon2 = Weapon; 00382 break; 00383 } 00384 } 00385 } 00386 else 00387 { 00388 if (!Player->Weapon1) 00389 { 00390 Player->Weapon1 = Weapon; 00391 } 00392 else if (!Player->Weapon2) 00393 { 00394 Player->Weapon2 = Weapon; 00395 } 00396 } 00397 return 1; 00398 } 00399 const char *getWeaponName(int index) 00400 { 00401 switch (index) 00402 { 00403 case 0:return "Empty"; break; 00404 case 1:return "Axe";break; 00405 case 2:return "Sword"; break; 00406 case 3:return "Flail"; break; 00407 } 00408 } 00409 00410 void setHealth(tPlayer *Player,int health) 00411 { 00412 if (health > 100) 00413 health = 100; 00414 if (health < 0) 00415 health = 0; 00416 Player->health = health; 00417 00418 } 00419 void setStrength(tPlayer *Player, byte strength) 00420 { 00421 if (strength > 100) 00422 strength = 100; 00423 if (strength < 0) 00424 strength = 0; 00425 Player->strength = strength; 00426 } 00427 void initPlayer(tPlayer *Player,tRealm *theRealm) 00428 { 00429 // get the player name 00430 int index=0; 00431 byte x,y; 00432 char ch=0; 00433 // Initialize the player's attributes 00434 eputs("Enter the player's name: "); 00435 while ( (index < MAX_NAME_LEN) && (ch != '\n') && (ch != '\r')) 00436 { 00437 ch = getUserInput(); 00438 if ( ch > '0' ) // strip conrol characters 00439 { 00440 00441 Player->name[index++]=ch; 00442 eputc(ch); 00443 } 00444 } 00445 Player->name[index]=0; // terminate the name 00446 setHealth(Player,100); 00447 Player->strength=50+random(50); 00448 Player->magic=50+random(50); 00449 Player->wealth=10+random(10); 00450 Player->Weapon1 = 0; 00451 Player->Weapon2 = 0; 00452 // Initialize the player's location 00453 // Make sure the player does not land 00454 // on an occupied space to begin with 00455 do { 00456 x=random(MAP_WIDTH); 00457 y=random(MAP_HEIGHT); 00458 00459 } while(theRealm->map[y][x] != '.'); 00460 Player->x=x; 00461 Player->y=y; 00462 } 00463 void showPlayer(tPlayer *thePlayer) 00464 { 00465 eputs("\r\nName: "); 00466 printString(thePlayer->name); 00467 eputs("health: "); 00468 printHex(thePlayer->health); 00469 eputs("\r\nstrength: "); 00470 printHex(thePlayer->strength); 00471 eputs("\r\nmagic: "); 00472 printHex(thePlayer->magic); 00473 eputs("\r\nwealth: "); 00474 printHex(thePlayer->wealth); 00475 eputs("\r\nLocation : "); 00476 printHex(thePlayer->x); 00477 eputs(" , "); 00478 printHex(thePlayer->y); 00479 eputs("\r\nWeapon1 : "); 00480 printString(getWeaponName(thePlayer->Weapon1)); 00481 eputs("Weapon2 : "); 00482 printString(getWeaponName(thePlayer->Weapon2)); 00483 } 00484 void initRealm(tRealm *Realm) 00485 { 00486 int x,y; 00487 int Rnd; 00488 // clear the map to begin with 00489 for (y=0;y < MAP_HEIGHT; y++) 00490 { 00491 for (x=0; x < MAP_WIDTH; x++) 00492 { 00493 Rnd = random(100); 00494 00495 if (Rnd >= 98) // put in some baddies 00496 Realm->map[y][x]= Baddies[random(sizeof(Baddies))]; 00497 else if (Rnd >= 95) // put in some good stuff 00498 Realm->map[y][x]= FindTypes[random(sizeof(FindTypes))]; 00499 else if (Rnd >= 90) // put in some rocks 00500 Realm->map[y][x]='*'; 00501 else // put in empty space 00502 Realm->map[y][x] = '.'; 00503 } 00504 } 00505 00506 // finally put the exit to the next level in 00507 x = random(MAP_WIDTH); 00508 y = random(MAP_HEIGHT); 00509 Realm->map[y][x]='X'; 00510 } 00511 void showRealm(tRealm *Realm,tPlayer *thePlayer) 00512 { 00513 int x,y; 00514 printString("The Realm:"); 00515 for (y=0;y<MAP_HEIGHT;y++) 00516 { 00517 for (x=0;x<MAP_WIDTH;x++) 00518 { 00519 00520 if ( (x==thePlayer->x) && (y==thePlayer->y)) 00521 eputc('@'); 00522 else 00523 eputc(Realm->map[y][x]); 00524 } 00525 eputs("\r\n"); 00526 } 00527 printString("\r\nLegend"); 00528 printString("(T)roll, (O)gre, (D)ragon, (H)ag, e(X)it"); 00529 printString("(w)eapon, (g)old), (m)agic, (s)trength"); 00530 printString("@=You"); 00531 } 00532 void showHelp() 00533 { 00534 00535 printString("Help"); 00536 printString("N,S,E,W : go North, South, East, West"); 00537 printString("# : show map (cost: 1 gold piece)"); 00538 printString("(H)elp"); 00539 printString("(P)layer details"); 00540 00541 } 00542 00543 void showGameMessage(char *Msg) 00544 { 00545 printString(Msg); 00546 printString("Ready"); 00547 } 00548 char getUserInput() 00549 { 00550 char ch = 0; 00551 00552 while (ch == 0) 00553 { 00554 ch = egetc(); 00555 prbs(); // cycle the prbs generator while waiting for user input 00556 } 00557 return ch; 00558 } 00559 unsigned prbs() 00560 { 00561 // This is an unverified 31 bit PRBS generator 00562 // It should be maximum length but this has not been verified 00563 static unsigned long shift_register=0xa5a5a5a5; 00564 unsigned long new_bit=0; 00565 static int busy=0; // need to prevent re-entrancy here 00566 if (!busy) 00567 { 00568 busy=1; 00569 new_bit= ((shift_register & (1<<27))>>27) ^ ((shift_register & (1<<30))>>30); 00570 new_bit= ~new_bit; 00571 new_bit = new_bit & 1; 00572 shift_register=shift_register << 1; 00573 shift_register=shift_register | (new_bit); 00574 busy=0; 00575 } 00576 return shift_register & 0x7ffffff; // return 31 LSB's 00577 } 00578 unsigned random(unsigned range) 00579 { 00580 // Implementing my own version of modulus 00581 // as it is a lot smaller than the library version 00582 // To prevent very long subtract loops, the 00583 // size of the value returned from prbs has been 00584 // restricted to 8 bits. 00585 int Rvalue = (prbs()&0xff); 00586 while (Rvalue >= range) 00587 Rvalue -= range; 00588 return Rvalue; 00589 } 00590 void zap() 00591 { 00592 00593 }
Generated on Thu Jul 21 2022 10:42:25 by
1.7.2