├── README.md ├── volume1 ├── bunny.c ├── hamurabi.c ├── nicomachus.c └── number.c └── volume2 ├── camel.c ├── column.c └── corral.c /README.md: -------------------------------------------------------------------------------- 1 | # Basic Computer Games 2 | 3 | Games included in David Ahl's books "Basic Computer Games" ported to C. 4 | 5 | ## Intro 6 | 7 | The second volume was one of my first type-ins books, but the Basic 8 | code used in the book was already archaic, and required porting to run 9 | on the Amstrad CPC 464. 10 | 11 | The first volume recently came into my hands, so depending on 12 | available time, I plan to port the games to C. 13 | 14 | ## Methodology 15 | 16 | The original code was written in 1970s era Micro$oft Basic, for 17 | apparently the lowest common denominator platform of the day. 18 | I have chosen to port the programs to appear similar to how I imagine 19 | the originals looked, but to use the availability of lower case 20 | characters in code and data. 21 | 22 | Perhaps out of design, the original code tends to be very unstructured, 23 | with goto's transferring execution to far away locations. I will 24 | restructure the code to give explanatory names to game functions. 25 | 26 | If I notice that the game could be improved with altered parameters, 27 | I will do so, but include comments with the old values. 28 | 29 | ## Compiling 30 | 31 | Instructions to compile are given in the source. 32 | 33 | ## Issues 34 | 35 | There is currently no one true way of obtaining random numbers, so the 36 | parts of the programs using random seeders and readers may have to be 37 | adapted. Currently uses arc4random_uniform(3) to obtain random numbers, 38 | on Linux this requires linking in libbsd. 39 | 40 | ## Licence 41 | 42 | GPLv3 43 | -------------------------------------------------------------------------------- /volume1/bunny.c: -------------------------------------------------------------------------------- 1 | // Bunny 2 | // Basic Computer Games 3 | // Workman Publishing 4 | // Converted to C by Michael Stroucken 5 | 6 | // cc -o bunny bunny.c 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Draws an ASCII art rendering of a men's magazine's bunny logo 13 | // Not much of a game, but the picture encoding is interesting 14 | 15 | int data1[] = { 2, 21, 14, 14, 25 }; // BUNNY ascii offsets 16 | 17 | // -1 = newline, 4096 = end, otherwise pairs of start and end 18 | // end horizontal position 19 | int data2[] = { 20 | 1, 2, -1, 0, 2, 45, 50, -1, 0, 5, 43, 52, -1, 0, 7, 41, 52, -1, 21 | 1, 9, 37, 50, -1, 2, 11, 36, 50, -1, 3, 13, 34, 49, -1, 4, 14, 32, 48, -1, 22 | 5, 15, 31, 47, -1, 6, 16, 30, 45, -1, 7, 17, 29, 44, -1, 8, 19, 28, 43, -1, 23 | 9, 20, 27, 41, -1, 10, 21, 26, 40, -1, 11, 22, 25, 38, -1, 12, 22, 24, 36, -1, 24 | 13, 34, -1, 14, 33, -1, 15, 31, -1, 17, 29, -1, 18, 27, -1, 25 | 19, 26, -1, 16, 28, -1, 13, 30, -1, 11, 31, -1, 10, 32, -1, 26 | 8, 33, -1, 7, 34, -1, 6, 13, 16, 34, -1, 5, 12, 16, 35, -1, 27 | 4, 12, 16, 35, -1, 3, 12, 15, 35, -1, 2, 35, -1, 1, 35, -1, 28 | 2, 34, -1, 3, 34, -1, 4, 33, -1, 6, 33, -1, 10, 32, 34, 34, -1, 29 | 14, 17, 19, 25, 28, 31, 35, 35, -1, 15, 19, 23, 30, 36, 36, -1, 30 | 14, 18, 21, 21, 24, 30, 37, 37, -1, 13, 18, 23, 29, 33, 38, -1, 31 | 12, 29, 31, 33, -1, 11, 13, 17, 17, 19, 19, 22, 22, 24, 31, -1, 32 | 10, 11, 17, 18, 22, 22, 24, 24, 29, 29, -1, 33 | 22, 23, 26, 29, -1, 27, 29, -1, 28, 29, -1, 4096}; 34 | 35 | void tab(int num) { 36 | int i; 37 | for (i=0; i 128) { 56 | goto end; 57 | } else { 58 | tab(x - pos); 59 | pos = x; 60 | y = data2[index++]; 61 | for (int i = x; i <= y; i ++) { 62 | int j = i - 5 * (i / 5); 63 | printf("%c", 64 + data1[j]); 64 | pos++; 65 | } 66 | } 67 | goto loop; 68 | 69 | end: 70 | printf("\n\n\n\n\n\n"); 71 | return; 72 | } 73 | 74 | 75 | 76 | 77 | int main() { 78 | tab(33);printf("Bunny\n"); 79 | tab(15);printf("Creative Computing Morristown, New Jersey\n"); 80 | printf("\n\n\n"); 81 | 82 | game(); 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /volume1/hamurabi.c: -------------------------------------------------------------------------------- 1 | // Hamurabi 2 | // Basic Computer Games 3 | // Workman Publishing 4 | // Converted to C by Michael Stroucken 5 | 6 | // cc -o hamurabi hamurabi.c 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // David Ahl's note: 13 | // This program was originally written in Focal at DEC; author unknown. 14 | // David Ahl converted it to BASIC and added the 10-year performance 15 | // accessment. If you wish to change any of the factors, the extensive 16 | // remarks in the program should make modification fairly straightforward. 17 | // Note for trivia buffs: Somewhere along the line an m was dropped out of 18 | // the spelling of Hammurabi in the Ahl version of the computer program. 19 | // This error has spread far and wide until a generation of students 20 | // who have used this program now think that Hammurabi is the incorrect 21 | // spelling. 22 | 23 | // Porter's note: 24 | // The particular impetus to port this game came from a side discussion 25 | // held at Demosplash 2017 at Carnegie-Mellon University 26 | // in Pittsburgh PA US. 27 | 28 | void tab(int num) { 29 | int i; 30 | for (i=0; i plague) { 68 | printf("A horrible plague struck! Half the people died.\n"); 69 | population >>= 1; 70 | } 71 | 72 | printf("Population is now %d.\n", population); 73 | printf("The city now owns %d acres.\n", acres); 74 | printf("You harvested %d bushels per acre.\n", bushelAcre); 75 | printf("Rats ate %d bushels.\n", ratfood); 76 | printf("You now have %d bushels in store.\n", grain); 77 | printf("\n"); 78 | 79 | if (year == 11) goto endOfTerm; 80 | 81 | bushelAcre = 17 + fnr(10); 82 | 83 | printf("Land is trading at %d bushels per acre.\n", bushelAcre); 84 | 85 | buy: 86 | printf("How many acres do you wish to buy? "); 87 | getline(&line, &linecap, stdin); 88 | val = atoi(line); 89 | if (val < 0) goto badInputExit; 90 | 91 | if (val * bushelAcre > grain) { 92 | printf("Hamurabi: Think again. You have only\n"); 93 | printf("%d bushels of grain. Now then:\n", grain); 94 | goto buy; 95 | } 96 | 97 | acres += val; grain -= val * bushelAcre; 98 | 99 | sell: 100 | printf("How many acres do you wish to sell? "); 101 | getline(&line, &linecap, stdin); 102 | val = atoi(line); 103 | if (val < 0) goto badInputExit; 104 | 105 | if (val >= acres) { 106 | printf("Hamurabi: Think again. You only own "); 107 | printf("%d acres. Now then:\n", acres); 108 | goto sell; 109 | } 110 | 111 | acres -= val; grain += val * bushelAcre; 112 | printf("\n"); 113 | 114 | feed: 115 | printf("How many bushels do you wish to feed your people? "); 116 | getline(&line, &linecap, stdin); 117 | val = atoi(line); 118 | if (val < 0) goto badInputExit; 119 | 120 | if (val > grain) { 121 | // Trying to use more grain than is in silos? 122 | printf("Hamurabi: Think again. You have only\n"); 123 | printf("%d bushels of grain. Now then:\n", grain); 124 | goto feed; 125 | } 126 | 127 | int food = val; 128 | grain -= food; 129 | printf("\n"); 130 | 131 | plant: 132 | printf("How many acres do you wish to plant with seed? "); 133 | getline(&line, &linecap, stdin); 134 | val = atoi(line); 135 | if (val < 0) goto badInputExit; 136 | 137 | if (val > acres) { 138 | // Trying to plant more acres than you own? 139 | printf("Hamurabi: Think again. You only own "); 140 | printf("%d acres. Now then:\n", acres); 141 | goto plant; 142 | } 143 | 144 | if (val/2 > grain) { 145 | // Enough grain for seed? 146 | printf("Hamurabi: Think again. You have only\n"); 147 | printf("%d bushels of grain. Now then:\n", grain); 148 | goto plant; 149 | } 150 | 151 | if (val > population * 10) { 152 | // Enough people to tend the crops? 153 | printf("But you have only %d people to tend the fields! Now then:\n", population); 154 | goto plant; 155 | } 156 | 157 | int planted = val; 158 | grain -= planted/2; 159 | 160 | int coin = fnr(5) + 1; 161 | 162 | // A bountiful harvest! 163 | bushelAcre = coin; 164 | harvest = planted * bushelAcre; 165 | 166 | coin = fnr(5) + 1; 167 | ratfood = 0; 168 | 169 | if (!(coin & 1)) { 170 | // rats are running wild!! 171 | ratfood = grain / coin; 172 | } 173 | 174 | grain -= ratfood; 175 | grain += harvest; 176 | 177 | coin = fnr(5) + 1; 178 | // let's have some babies 179 | immigration = coin * (20 * acres + grain) / population / 100 + 1; 180 | 181 | // how many people had full tummies? 182 | int fedPeople = food / 20; 183 | 184 | // Horror, a 15% chance of plague 185 | plague = fnr(100) - 15; 186 | 187 | if (population >= fedPeople) { 188 | // Starve enough for impeachment? 189 | dead = population - fedPeople; 190 | if (dead > 0.45* population) { 191 | printf("\n"); 192 | printf("You starved %d people in one year!!!\n", dead); 193 | goto impeachment; 194 | } 195 | } 196 | 197 | deathrate = ((year-1) * deathrate + dead * 100 / population) / year; 198 | population = fedPeople; 199 | totalDead += dead; 200 | goto round; 201 | 202 | impeachment: 203 | printf("Due to this extreme mismanagement you have not only\n"); 204 | printf("been impeached and thrown out of office but you have\n"); 205 | printf("also been declared national fink!!!!\n"); 206 | goto end; 207 | 208 | badInputExit: 209 | printf("Hamurabi: I cannot do what you wish.\n"); 210 | printf("Get yourself another steward!!!!!\n"); 211 | goto end; 212 | 213 | endOfTerm: 214 | printf("In your 10-year term of office, %d percent of the\n", deathrate); 215 | printf("population starved per year on the average, i.e. a total of\n"); 216 | printf("%d people died!!\n", totalDead); 217 | 218 | int acresPerson = acres / population; 219 | printf("You started with 10 acres per person and ended with\n"); 220 | printf("%d acres per person.\n", acresPerson); 221 | 222 | printf("\n"); 223 | 224 | if (deathrate > 33 || acresPerson < 7) goto impeachment; 225 | 226 | if (deathrate > 10 || acresPerson < 9) { 227 | printf("Your heavy-handed performance smacks of Nero and Ivan IV.\n"); 228 | printf("The people (remaining) find you an unpleasant ruler, and,\n"); 229 | printf("frankly, hate your guts!!\n"); 230 | } else if (deathrate > 3 || acresPerson < 10) { 231 | printf("Your performance could have been somewhat better, but\n"); 232 | printf("really wasn't too bad at all. "); 233 | int num = fnr(80) * population / 100; 234 | printf("%d people\n", num); 235 | printf("dearly like to see you assassinated but we all have our\n"); 236 | printf("trivial problems.\n"); 237 | } else { 238 | printf("A fantastic performance!!! Charlemagne, Disraeli, and\n"); 239 | printf("Jefferson combined could not have done better!\n"); 240 | } 241 | 242 | end: 243 | printf("\n"); 244 | // original rang bell 10 times 245 | printf("So long for now.\n"); 246 | return; 247 | } 248 | 249 | int main() { 250 | 251 | tab(32);printf("Hamurabi\n"); 252 | tab(15);printf("Creative Computing Morristown, New Jersey\n"); 253 | printf("\n\n\n"); 254 | printf("Try your hand at governing ancient Sumeria\n"); 255 | printf("for a ten-year term of office.\n"); 256 | 257 | game(); 258 | 259 | return 0; 260 | } 261 | -------------------------------------------------------------------------------- /volume1/nicomachus.c: -------------------------------------------------------------------------------- 1 | // Nicomachus 2 | // Basic Computer Games 3 | // Workman Publishing 4 | // Converted to C by Michael Stroucken 5 | // Original by David Ahl 6 | 7 | // cc -o nicomachus nicomachus.c 8 | 9 | // This puzzle was first derived by Nicomachos in 90 CE. 10 | // and published in his "Arithmetica" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // The original apparently didn't exercise the codepath 18 | // when a user does not answer with yes or no when asked. 19 | // The original has the code jump back to a non-existent 20 | // line number in that case. 21 | // This functionality has been fixed, along with missing 22 | // punctuation added when the user's input is quoted back 23 | // to him. 24 | 25 | void tab(int num) { 26 | int i; 27 | for (i=0; i 13 | #include 14 | #include 15 | 16 | // A check was added to check for invalid guesses below 1. 17 | // It seems the game actually picks 5 random values, and 18 | // does stuff to the point balance depending on which one 19 | // matches the user's guess. 20 | // There is no consideration of the game's guesses being 21 | // distinct. 22 | // Added a check if points are zero or less. 23 | 24 | 25 | void tab(int num) { 26 | int i; 27 | for (i=0; i 5 || guess < 1) { 55 | goto inputGuess; 56 | } 57 | 58 | int r = fnr(); 59 | int s = fnr(); 60 | int t = fnr(); 61 | int u = fnr(); 62 | int v = fnr(); 63 | 64 | int checked = 0; 65 | if (guess == r) { 66 | p -= 5; 67 | checked = 1; 68 | } 69 | 70 | if (!checked && guess == s) { 71 | p += 5; 72 | checked = 1; 73 | } 74 | 75 | if (!checked && guess == t) { 76 | p *= 2; 77 | printf("You hit the jackpot!!!\n"); 78 | checked = 1; 79 | } 80 | 81 | if (!checked && guess == u) { 82 | p += 1; 83 | checked = 1; 84 | } 85 | 86 | if (!checked && guess == v) { 87 | p /= 2; 88 | checked = 1; 89 | } 90 | 91 | if (!checked) { 92 | // what now? 93 | } 94 | 95 | if (p > 500) { 96 | printf("!!!!You win!!!! with %d points.", p); 97 | isDone = 1; 98 | } 99 | 100 | if (p <= 0) { 101 | printf("You have no more points to play with.\n"); 102 | isDone = 1; 103 | } 104 | 105 | if (!isDone) { 106 | printf("You have %d points.\n", p); 107 | } 108 | } while (!isDone); 109 | } 110 | 111 | 112 | 113 | 114 | int main() { 115 | 116 | tab(33);printf("Number\n"); 117 | tab(15);printf("Creative Computing Morristown, New Jersey\n"); 118 | printf("\n\n\n"); 119 | printf("You have 100 points. By guessing numbers from 1 to 5, you\n"); 120 | printf("can gain or lose points depending upon how close you get to\n"); 121 | printf("a random number selected by the computer.\n"); 122 | printf("\n"); 123 | printf("You occasionally will get a jackpot which will double(!)\n"); 124 | printf("your point count. You win when you get 500 points.\n"); 125 | 126 | game(); 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /volume2/camel.c: -------------------------------------------------------------------------------- 1 | // Camel 2 | // Basic-Computer-Spiele Band 2 3 | // Sybex Verlag 4 | // Converted to C by Michael Stroucken 5 | // Original by the Heath Users Group 6 | 7 | // cc -o camel camel.c 8 | 9 | // Porter's notes: 10 | // I think the pygmies are far too strong and the game is almost 11 | // impossible without adjustments. 12 | // 13 | // I tried to remove gameplay bugs, but I kept the particular 14 | // misspellings from the original. 15 | // 16 | // Gobi Desert, camel, pygmies, sheiks? Knock-kneed? 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | struct game_state_t { 23 | int water_level; 24 | int drinks_left; 25 | int camel_distance; 26 | int pygmy_distance; 27 | int berber_mode; 28 | int camel_stress; 29 | int turn_count; 30 | }; 31 | 32 | typedef struct game_state_t game_state; 33 | 34 | void tab(int num) { 35 | int i; 36 | for (i=0; iwater_level = 4; 48 | state->drinks_left = 6; 49 | state->camel_distance = 0; 50 | state->pygmy_distance = 0; 51 | state->berber_mode = 0; 52 | state->camel_stress = 0; 53 | state->turn_count = 0; 54 | } 55 | 56 | void die() { 57 | printf("You died in the desert.\n"); 58 | int val = fnr(10); 59 | if (val <= 1) { 60 | printf("The national camel's union is not attending your funeral!!!\n"); 61 | } else if (val <= 3) { 62 | printf("Your body was eaten by vultures and imported canninbals !!!\n"); 63 | } else if (val <= 5) { 64 | printf("The local sheik now uses your skull for a change purse !!!\n"); 65 | } else if (val <= 7) { 66 | printf("People with little intelligence should stay out of the desert\n"); 67 | } else { 68 | printf("Turkeys should fly, not ride camels !!!!!!!\n"); 69 | } 70 | } 71 | 72 | int berber(game_state* state) { 73 | printf("#7 Attempt an escape\n"); 74 | printf("#8 Wait for payment\n"); 75 | printf("Your sub-command ? \n"); 76 | 77 | char *line = NULL; 78 | size_t linecap = 0; 79 | getline(&line, &linecap, stdin); 80 | 81 | int value = atoi(line); 82 | free(line); 83 | 84 | if (value == 8) { 85 | int val = fnr(100); 86 | if (val < 25) { 87 | printf("Your ransom has been paid and you are free to go.\n"); 88 | state->berber_mode = 0; 89 | return 0; 90 | } 91 | 92 | printf("The local sultan is collecting.......Just wait.......\n"); 93 | return 0; 94 | } 95 | 96 | int val = fnr(10); 97 | if (val < 5) { 98 | printf("You were mortally wounded by a pig stabber while escaping.\n"); 99 | die(); 100 | return 1; 101 | } 102 | 103 | printf("Congradulations, you successfully escaped !!!!\n"); 104 | state->berber_mode = 0; 105 | return 0; 106 | } 107 | 108 | void random_events(game_state* state) { 109 | int val = fnr(100); 110 | if (val <= 5) { 111 | printf("Wild Berbers hidden in the sand have captured you.\n"); 112 | printf("Luckily the local sheik has agreed to their ransom-\n"); 113 | printf("demands.......but........watch for the pygmies !!!\n"); 114 | printf("You have a new choice of sub-commands\n"); 115 | state->berber_mode = 1; 116 | return; 117 | } 118 | 119 | val = fnr(10); 120 | if (val <= 2) { 121 | printf("You have arrived at an oases--------Your camel is\n"); 122 | printf("filling your canteen and eating figs.\n"); 123 | state->water_level = 4; 124 | state->drinks_left = 6; 125 | return; 126 | } 127 | 128 | val = fnr(100); 129 | if (val <= 5) { 130 | printf("You have been caught in a sandstorm.....Good luck!\n"); 131 | int distance = fnr(10); 132 | int direction = fnr(10); 133 | if (direction & 1) { 134 | state->camel_distance += distance; 135 | } else { 136 | state->camel_distance -= distance; 137 | } 138 | 139 | printf("Your new position is %d miles so far!\n", state->camel_distance); 140 | return; 141 | } 142 | 143 | val = fnr(100); 144 | if (val <= 5) { 145 | state->pygmy_distance++; 146 | printf("Your camel hurt his hump\n"); 147 | printf("Luckily the pygmies were footweary !!!\n"); 148 | return; 149 | } 150 | 151 | return; 152 | } 153 | 154 | void camel_dead() { 155 | printf("You dirty rapscallion! You ran your poor camel to death !!\n"); 156 | die(); 157 | } 158 | 159 | void game() { 160 | game_state state; 161 | 162 | printf("Good luck and good cameling !!\n"); 163 | printf("You are in the middle of the desert at an oasis.\n"); 164 | 165 | init_game(&state); 166 | 167 | while (1) { 168 | if (state.camel_distance > 199) { 169 | printf("You win, a party is being given in your honor.......\n"); 170 | printf(".......The pygmies are planning to attend.......\n"); 171 | return; 172 | } 173 | 174 | state.water_level--; 175 | if (state.water_level == 1) { 176 | printf("----------WARNING---------- Get a drink\n"); 177 | } 178 | 179 | if (state.water_level < 0) { 180 | printf("You ran out of water...... Sorry chum!!!\n"); 181 | return; 182 | } 183 | 184 | state.turn_count++; 185 | 186 | // pygmies are a bit faster than moderate camel speed 187 | int pygmy_advance = (fnr(100)+25)/10; 188 | 189 | // pygmies start after turn 3 190 | if (state.turn_count >= 4) { 191 | state.pygmy_distance += pygmy_advance; 192 | } 193 | 194 | // by source, the pygmies don't advance in Berber mode 195 | // by source, Berber mode is never set 196 | if (state.berber_mode) { 197 | if (berber(&state)) { 198 | return; 199 | } 200 | 201 | continue; 202 | } 203 | 204 | if (state.turn_count >= 4) { 205 | if (state.pygmy_distance > state.camel_distance) { 206 | printf("The pygmies have captured you. Camel and people soup is\n"); 207 | printf("their favorite dish !!!!!\n"); 208 | return; 209 | } 210 | 211 | int separation = state.camel_distance - state.pygmy_distance; 212 | printf("The pygmies are %d miles behind you.\n", separation); 213 | } 214 | 215 | printf("You have travelled %d miles alltogether.\n", state.camel_distance); 216 | printf("What is your command? "); 217 | 218 | char *line = NULL; 219 | size_t linecap = 0; 220 | getline(&line, &linecap, stdin); 221 | 222 | int value = atoi(line); 223 | free(line); 224 | 225 | // source didn't try to fix errors 226 | 227 | if (value == 1) { 228 | state.drinks_left--; 229 | if (state.drinks_left < 0) { 230 | die(); 231 | return; 232 | } 233 | 234 | printf("Better watch for an oases !\n"); 235 | state.water_level = 4 + 1; // +1 for the turn cost 236 | continue; 237 | } else if (value == 2) { 238 | state.camel_stress++; 239 | if (state.camel_stress == 8) { 240 | camel_dead(); 241 | return; 242 | } 243 | 244 | // in source, game random events happened before movement 245 | int camel_advance = fnr(10); 246 | state.camel_distance += camel_advance; 247 | printf("Your camel likes this pace.\n"); 248 | 249 | random_events(&state); 250 | continue; 251 | } else if (value == 3) { 252 | state.camel_stress += 3; 253 | if (state.camel_stress >= 8) { 254 | camel_dead(); 255 | return; 256 | } 257 | 258 | // in source, game random events happened before movement 259 | int camel_advance = 2*fnr(10); 260 | state.camel_distance += camel_advance; 261 | printf("Your camel is burning across the desert sands.\n"); 262 | 263 | random_events(&state); 264 | continue; 265 | } else if (value == 4) { 266 | printf("Your camel thanks you!\n"); 267 | state.camel_stress = 0; 268 | continue; 269 | } else if (value == 5) { 270 | printf("Your camel has %d good days left.\n", 7 - state.camel_stress); 271 | printf("You have %d drinks left in your canteen.\n", state.drinks_left); 272 | printf("You can go %d commands without drinking.\n", state.water_level); 273 | // but pygmies still advance and water level decreases 274 | continue; 275 | } else { 276 | int chance = fnr(10); 277 | if (chance != 1) { 278 | die(); 279 | return; 280 | } 281 | 282 | // only 10% chance to live 283 | printf("Help has found you in a state of unconsciousness.\n"); 284 | state.drinks_left = 3; 285 | state.water_level = 4; 286 | continue; 287 | } 288 | } 289 | } 290 | 291 | int main() { 292 | char *line = NULL; 293 | size_t linecap = 0; 294 | 295 | tab(26);printf("Camel\n"); 296 | tab(20);printf("Creative Computing\n"); 297 | tab(18);printf("Morristown, New Jersey\n"); 298 | printf("\n\n\n"); 299 | printf("Would you like instructions? "); 300 | 301 | int compare=0; 302 | line = NULL; 303 | linecap = 0; 304 | getline(&line, &linecap, stdin); 305 | compare = strncasecmp(line, "n", 1); 306 | free(line); 307 | 308 | if (compare) { 309 | printf("\n"); 310 | printf(" Welcome to Camel. The object is to travel\n"); 311 | printf("200 miles across the great Gobi Desert.\n"); 312 | printf("A tribe of knock kneed pigmies will be chasing you.\n"); 313 | printf("You will be asked for commands every so often.\n"); 314 | printf("\n\n\n"); 315 | printf("C O M M A N D S :\n"); 316 | printf("#1 Drink from your canteen\n"); 317 | printf("#2 Ahead moderate speed\n"); 318 | printf("#3 Ahead full speed\n"); 319 | printf("#4 Stop for the night\n"); 320 | printf("#5 Status check\n"); 321 | printf("#6 Hope for help\n"); 322 | printf("\n\n\n\n\n"); 323 | printf("You have one quart of water which will last you six drinks.\n"); 324 | printf("You may renew your water supply completely at an oases.\n"); 325 | printf("You get a half a quart if found by help.\n"); 326 | printf("If help does not find you after command six, you lose.\n"); 327 | } 328 | 329 | compare = 0; 330 | do { 331 | game(); 332 | printf("\n\n"); 333 | printf("Want a new camel and a new game ?\n"); 334 | line = NULL; 335 | linecap = 0; 336 | getline(&line, &linecap, stdin); 337 | compare = strncasecmp(line, "y", 1); 338 | free(line); 339 | } while (!compare); 340 | 341 | printf("-----------------\n"); 342 | printf(" CHICKEN\n"); 343 | printf("-----------------\n"); 344 | 345 | return 0; 346 | } 347 | -------------------------------------------------------------------------------- /volume2/column.c: -------------------------------------------------------------------------------- 1 | // Column ("Saeule") 2 | // Basic-Computer-Spiele Band 2 3 | // Sybex Verlag 4 | // Converted to C by Michael Stroucken 5 | // Original by Alan Barnes 6 | 7 | // cc -o column column.c 8 | 9 | // The trick behind this game is that after the first round, 10 | // the matrix is read in column-major order and replaced in 11 | // row major order. Each new column of 9 cards contains 3 12 | // cards of the column that was chosen in the first round. 13 | // The process is repeated after the second round, after which 14 | // each column will contain one card from the 3 that shared 15 | // the column the user picked in the second round. The third 16 | // choice uniquely identifies the chosen card. 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | // In the original, the user chose from 21 cards in the deck, using 23 | // 3 iterations choosing from 3 options. 3^3 is 27, however, so 24 | // the game could also be played with a deck of 27 cards. If playing 25 | // with 21 cards, the user can lie and will receive a card in the 26 | // end anyway. 27 | 28 | #define DECKSIZE 27 29 | 30 | // Choose from all standard cards. 31 | #define NUMCARDS 52 32 | 33 | int deck[DECKSIZE]; 34 | 35 | void tab(int num) { 36 | int i; 37 | for (i=0; i 3) { 140 | printf("(1-3)\n"); 141 | } 142 | } while (column < 1 || column > 3); 143 | 144 | transform[1] = column; 145 | transform[2] = (column = (column % 3) + 1); 146 | transform[0] = (column = (column % 3) + 1); 147 | 148 | redeal(transform); 149 | return; 150 | } 151 | 152 | 153 | void game() { 154 | int round; 155 | int i; 156 | pickdeck(); 157 | for(round=1; round<=3; round++) { 158 | showround(); 159 | } 160 | 161 | int posSolution = DECKSIZE / 2; 162 | // originally: for(i=0; i<11+(random() % 10)+1; i++) { 163 | for(i=0; i < posSolution; i++) { 164 | printf("%s\n", cardname(deck[i])); 165 | } 166 | 167 | printf("\n"); 168 | printf("Oops!!! Your card is the "); 169 | printf("%s.\n", cardname(deck[posSolution])); 170 | 171 | return; 172 | } 173 | 174 | int main() { 175 | char *line = NULL; 176 | size_t linecap = 0; 177 | 178 | tab(26);printf("Column\n"); 179 | tab(20);printf("Creative Computing\n"); 180 | tab(18);printf("Morristown, New Jersey\n"); 181 | printf("\n\n\n"); 182 | printf("This program will show you a card trick, after the first deal\n"); 183 | printf("pick a card and type the number of the column containing it.\n"); 184 | printf("The dealer will then pick up the cards, a column at a time,\n"); 185 | printf("and will deal them out again horizontally. When he finishes\n"); 186 | printf("each time, type the number of the new column containing your\n"); 187 | printf("card, following the last deal the dealer will turn over the\n"); 188 | printf("cards, one at a time, until he reaches the one you picked.\n"); 189 | printf("\n\n\n"); 190 | 191 | int compare = 0; 192 | do { 193 | game(); 194 | printf("Do you want to see it again? "); 195 | line = NULL; 196 | linecap = 0; 197 | getline(&line, &linecap, stdin); 198 | compare = strncasecmp(line, "yes", 3); 199 | free(line); 200 | } while (!compare); 201 | 202 | return 0; 203 | } 204 | -------------------------------------------------------------------------------- /volume2/corral.c: -------------------------------------------------------------------------------- 1 | // Corral 2 | // Basic-Computer-Spiele Band 2 3 | // Sybex Verlag 4 | // Converted to C by Michael Stroucken 5 | // Original by Colin Keay 6 | 7 | // cc -o corral corral.c 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | const int p[] = {0, 1, 2, 3, 3, 2, 2, 1, 0, -1}; 14 | const int q[] = {1, 2, 3, 4, 5, 4, 3, 2, 1, 0}; 15 | 16 | #define ARENASIZE 21 17 | 18 | void tab(int num) { 19 | int i; 20 | for (i=0; i ARENASIZE - 1) *horsePos = ARENASIZE - 1; 39 | } 40 | 41 | void setupArena(char* arena, int cowboyPos, int horsePos) { 42 | memset(arena, ' ', ARENASIZE); 43 | if (cowboyPos == horsePos) { 44 | arena[cowboyPos] = '#'; 45 | } else { 46 | arena[cowboyPos] = 'C'; 47 | arena[horsePos] = 'H'; 48 | } 49 | } 50 | 51 | void game() { 52 | char arena[ARENASIZE+1]; 53 | arena[ARENASIZE] = 0; 54 | int cowboyPos = 0; // starts at left edge 55 | int cowboyLeftOfHorse = 1; 56 | int kickFlight = 0; 57 | int moveCount = 0; 58 | int kickCount = 0; 59 | int horsePos, randomVal, pVal, qVal, cowboyHitpoints; 60 | char *action; 61 | getRandomState(&randomVal, &pVal, &qVal); 62 | 63 | if (randomVal > 5) { 64 | qVal = -qVal; 65 | } 66 | 67 | horsePos = 13 + qVal; 68 | boundHorse(&horsePos); 69 | 70 | cowboyHitpoints = 2 + pVal; 71 | printf("\n"); 72 | 73 | action = " "; 74 | while (1) { 75 | setupArena(arena, cowboyPos, horsePos); 76 | printf("%d\tI%sI\t%s", moveCount, arena, action); 77 | int distance = horsePos - cowboyPos; 78 | cowboyLeftOfHorse = (distance > 0) ? 1 : -1; 79 | distance = abs(distance); 80 | 81 | moveCount++; 82 | if (kickFlight > 0) { 83 | if (kickCount > cowboyHitpoints) { 84 | printf("\n"); 85 | printf("Those kicks landed you in the hospital!\n"); 86 | printf(" Get well soon!!\n"); 87 | return; 88 | } 89 | 90 | kickFlight--; 91 | printf("\n"); 92 | getRandomState(&randomVal, &pVal, &qVal); 93 | horsePos = horsePos + cowboyLeftOfHorse * (pVal + 1); 94 | boundHorse(&horsePos); 95 | action = " "; 96 | continue; 97 | } 98 | 99 | if (moveCount > 100) { 100 | printf("\n"); 101 | printf("Enough!! You'd do better as camp cook!\n"); 102 | return; 103 | } 104 | 105 | int moveInput; 106 | int inputOk = 0; 107 | while (!inputOk) { 108 | char *line = NULL; 109 | size_t linecap = 0; 110 | printf("? "); 111 | getline(&line, &linecap, stdin); 112 | moveInput = atoi(line); 113 | free(line); 114 | 115 | if (moveInput > 0 && moveInput < 6) { 116 | int cowboyTarget = cowboyPos + cowboyLeftOfHorse * moveInput; 117 | if (cowboyTarget >= 0 && cowboyTarget < ARENASIZE) { 118 | inputOk = 1; 119 | cowboyPos = cowboyTarget; 120 | } 121 | } 122 | 123 | if (!inputOk) { 124 | printf("Illegal move. Try again\t"); 125 | } 126 | } 127 | 128 | getRandomState(&randomVal, &pVal, &qVal); 129 | horsePos = horsePos + cowboyLeftOfHorse * pVal; 130 | boundHorse(&horsePos); 131 | 132 | if (distance < 2 * moveInput && distance > 1) { 133 | goto bolt; 134 | } 135 | 136 | if (randomVal > 2 || (horsePos > 0 && horsePos < ARENASIZE - 1)) { 137 | if (abs(horsePos - cowboyPos) > 2) { 138 | action = " "; 139 | continue; 140 | } 141 | getRandomState(&randomVal, &pVal, &qVal); 142 | if (randomVal > 3) { 143 | if (horsePos == cowboyPos) { 144 | setupArena(arena, cowboyPos, horsePos); 145 | printf("\tI%sI\n", arena); 146 | printf("\n"); 147 | printf("Yippee!! Now see if you can catch him in fewer moves\n"); 148 | return; 149 | } 150 | action = " "; 151 | continue; 152 | } 153 | getRandomState(&randomVal, &pVal, &qVal); 154 | kickFlight = pVal + 2; 155 | kickCount++; 156 | horsePos = horsePos - 5 * cowboyLeftOfHorse; 157 | boundHorse(&horsePos); 158 | action = "kicked"; 159 | continue; 160 | } 161 | if (distance > 7) { 162 | action = " "; 163 | continue; 164 | } 165 | 166 | bolt: { 167 | int boltStrength = 9 + 2 * pVal; 168 | horsePos = horsePos - cowboyLeftOfHorse * boltStrength; 169 | boundHorse(&horsePos); 170 | if (abs(horsePos - cowboyPos) > 1) { 171 | } else { 172 | horsePos = horsePos - 3 * cowboyLeftOfHorse; 173 | } 174 | action = "bolted "; 175 | continue; 176 | } 177 | } 178 | 179 | } 180 | 181 | int main() { 182 | char *line = NULL; 183 | size_t linecap = 0; 184 | 185 | tab(26);printf("Corral\n"); 186 | tab(20);printf("Creative Computing\n"); 187 | tab(18);printf("Morristown, New Jersey\n"); 188 | printf("\n\n\n"); 189 | printf(" You are the cowboy. Go catch your horse in the corral!\n"); 190 | printf("Do you want full instructions? "); 191 | 192 | int compare=0; 193 | line = NULL; 194 | linecap = 0; 195 | getline(&line, &linecap, stdin); 196 | compare = strncasecmp(line, "n", 1); 197 | free(line); 198 | 199 | if (compare) { 200 | printf("You move toward your horse 1 to 5 steps at a time.\n"); 201 | printf("If you move more than half the separation, he will bolt!\n"); 202 | printf("He may also bolt when he is close to the rail.\n"); 203 | printf("When you come within 2 steps, he may kick. So look out!!\n"); 204 | printf("\n"); 205 | printf("After '?' type in digit from 1 to 5 for cowboy's next move\n"); 206 | } 207 | 208 | compare = 0; 209 | do { 210 | game(); 211 | printf("Another roundup? "); 212 | line = NULL; 213 | linecap = 0; 214 | getline(&line, &linecap, stdin); 215 | compare = strncasecmp(line, "y", 1); 216 | free(line); 217 | } while (!compare); 218 | 219 | return 0; 220 | } 221 | --------------------------------------------------------------------------------