PageRenderTime 49ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/brians7.cpp

https://github.com/misterque/gameofbrians
C++ | 396 lines | 265 code | 56 blank | 75 comment | 101 complexity | d086f90525d48796e21dee291057d5c7 MD5 | raw file
  1. /******************************************************************************
  2. Game of Brian's
  3. Copyright 2006 Dirk Fortmeier
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. *******************************************************************************/
  16. #include <string>
  17. #include <iostream>
  18. #include <SDL/SDL.h>
  19. using namespace std;
  20. #ifdef _WIN32
  21. #undef main
  22. #include <stdlib.h>
  23. #endif
  24. #define WIDTH 5 // width of each cell
  25. #define HEIGHT 5 // height of each cell
  26. #define SIZEX 100 // number of cells vertical
  27. #define SIZEY 100 // number of cells horizontal
  28. #define CALCPER 40 // numner of randomly picked cells per calc-cycle
  29. #define SHOWPER 10 // calc-cycles per frame
  30. // the cell structure
  31. struct Cell{
  32. bool alive; // is there a living cell?
  33. string BNA; // the Brian N A, a string in extended
  34. // brainfuck syntax
  35. signed char feld[20]; // the 'turing tape'
  36. signed char pfeld; // the pointer to the head's position
  37. signed char ZUP; // the CellEnvironmentPointer, pointing
  38. // to one of the surrounding cells
  39. int x,y; // the position of the cell
  40. unsigned char r,g,b; // the color of the cell
  41. int ribopos; // the position of the bna interpreter
  42. int resswert;
  43. };
  44. // initialise the cell-array
  45. Cell Feld[SIZEX][SIZEY];
  46. // some SDL code to draw the cell-array
  47. void show(SDL_Surface *screen)
  48. {
  49. Uint32 color, black;
  50. black = SDL_MapRGB(screen->format, 0,0,0);
  51. SDL_Rect rect;
  52. rect.h = WIDTH;
  53. rect.w = HEIGHT;
  54. SDL_LockSurface(screen);
  55. for (int y = 0;y<100;y++)
  56. for (int x = 0;x<100;x++)
  57. {
  58. rect.x = x*WIDTH;
  59. rect.y = y*HEIGHT;
  60. color = SDL_MapRGB(screen->format, Feld[x][y].r,
  61. Feld[x][y].g,
  62. Feld[x][y].b);
  63. if (Feld[x][y].alive == true) SDL_FillRect(screen, &rect, color);
  64. if (Feld[x][y].alive == false) SDL_FillRect(screen, &rect, black);
  65. };
  66. SDL_UnlockSurface(screen);
  67. SDL_UpdateRect(screen, 0, 0, 0, 0);
  68. };
  69. // a funtion returning a pointer to a cell
  70. Cell* GetCell(int x,int y) {
  71. if (x<0) x+=SIZEX;
  72. if (y<0) y+=SIZEY;
  73. if (x>SIZEX-1) x-=SIZEX;
  74. if (y>SIZEY-1) y-=SIZEY;
  75. return &Feld[x][y];
  76. }
  77. // a function returning a pointer to a cell the 'mother'-cells ZUP pointing to
  78. Cell* ZUPtoCell(Cell* Zelle){
  79. int x = Zelle->x;
  80. int y = Zelle->y;
  81. if (Zelle->ZUP == 0) { x ; y--; }
  82. else if(Zelle->ZUP == 1) { x++ ; y--; }
  83. else if(Zelle->ZUP == 2) { x++ ; y; }
  84. else if(Zelle->ZUP == 3) { x++ ; y++; }
  85. else if(Zelle->ZUP == 4) { x ; y++; }
  86. else if(Zelle->ZUP == 5) { x-- ; y++; }
  87. else if(Zelle->ZUP == 6) { x-- ; y; }
  88. else if(Zelle->ZUP == 7) { x-- ; y--; }
  89. return GetCell(x,y);
  90. }
  91. // a function to generate extendend brainfuck commands
  92. string GetToken() {
  93. string s;
  94. switch(rand()%10){
  95. case 0: s = "<"; break;
  96. case 1: s = ">"; break;
  97. case 2: s = "+"; break;
  98. case 3: s = "-"; break;
  99. case 4: s = "{"; break;
  100. case 5: s = "}"; break;
  101. case 6: s = "["; break;
  102. case 7: s = "]"; break;
  103. case 8: s = "."; break;
  104. case 9: s = ","; break;
  105. }
  106. return s;
  107. }
  108. // yet another helper funtion for randoms
  109. bool rnd(int pro){
  110. if (rand()%pro != 0) return true;
  111. else return false;
  112. }
  113. //mutation rate
  114. int mutarate=5;
  115. bool dodeathfunc = false;
  116. // this function copies a cell to the location the ZUP points to
  117. void CPCell(Cell* Zelle){
  118. if(dodeathfunc && Zelle->resswert < 5 ) return;
  119. Cell *Celle = ZUPtoCell(Zelle);
  120. int x = Celle->x; int y = Celle->y;
  121. *Celle = *Zelle;
  122. Celle->x = x;
  123. Celle->y = y;
  124. Celle->ribopos=0;
  125. for(int n=0; n<20; n++)
  126. Celle->feld[n] = 0;
  127. //here, the BNA is randomly changed
  128. if(!rnd(mutarate)){
  129. if(rand()%2)
  130. Celle->BNA.insert(rand()%Celle->BNA.size(), GetToken());
  131. else
  132. if(Celle->BNA.size() >20) Celle->BNA.erase(rand()%Celle->BNA.size(), 1);
  133. Celle->r += (rand()%3 - 1) * 5;
  134. Celle->g += (rand()%3 - 1) * 5;
  135. Celle->b += (rand()%3 - 1) * 5;
  136. }
  137. }
  138. // the cells sensory ',' funtion, sets the value the pfeld is pointing to to
  139. // zero if the ZUP points to a living cell
  140. void CheckCell(Cell* Zelle){
  141. if(ZUPtoCell(Zelle)->alive) {
  142. Zelle->feld[Zelle->pfeld] = 0;
  143. }
  144. }
  145. // the brainfuck (extended) interpreter
  146. // it interprets the following commands:
  147. // '>' increments the pfeld pointer
  148. // '<' decrements the pfeld pointer
  149. // '+' increments the tape's current value
  150. // '-' decrements the tape's current value
  151. // '{' increments the ZUP (extended syntax)
  152. // '}' decrements the ZUP (extended syntax)
  153. // '.' copies the cell to the ZUP (changed syntax)
  154. // ',' checks for living cell at the ZUP (changed syntax)
  155. // '[' loop construct
  156. // ']' loop construct, to prevent infinite loops it aborts randomly
  157. //
  158. void BrainFuck(Cell* Zelle){
  159. if(Zelle->ribopos == Zelle->BNA.size()) Zelle->ribopos = 0;
  160. int pos = Zelle->ribopos;
  161. if(Zelle->BNA.at(pos) == '>') {
  162. Zelle->pfeld +=1;
  163. if(Zelle->pfeld > 19) Zelle->pfeld-=20;
  164. }
  165. else if(Zelle->BNA.at(pos) == '<') {
  166. Zelle->pfeld -=1;
  167. if(Zelle->pfeld < 0) Zelle->pfeld+=20;
  168. }
  169. else if(Zelle->BNA.at(pos) == '+') {
  170. Zelle->feld[Zelle->pfeld] +=1;
  171. }
  172. else if(Zelle->BNA.at(pos) == '-') {
  173. Zelle->feld[Zelle->pfeld] -=1;
  174. }
  175. else if(Zelle->BNA.at(pos) == '{') {
  176. Zelle->ZUP++;
  177. if(Zelle->ZUP > 7) Zelle->ZUP-=8;
  178. }
  179. else if(Zelle->BNA.at(pos) == '}') {
  180. Zelle->ZUP--;
  181. if(Zelle->ZUP < 0) Zelle->ZUP+=8;
  182. }
  183. else if(Zelle->BNA.at(pos) == '.') {
  184. CPCell(Zelle);
  185. }
  186. else if(Zelle->BNA.at(pos) == ',') {
  187. CheckCell(Zelle);
  188. }
  189. /*else if(Zelle->BNA.at(pos) == '[') {
  190. if(Zelle->feld[Zelle->pfeld] == 0 ) {
  191. while(pos < Zelle->BNA.size() && Zelle->BNA.at(pos) != ']' ) {
  192. pos++;
  193. }
  194. }
  195. }
  196. else if(Zelle->BNA.at(pos) == ']') {
  197. if(Zelle->feld[Zelle->pfeld] != 0 && rnd(4) ) {
  198. while(pos !=0 && Zelle->BNA.at(pos) != '[' ) {
  199. pos--;
  200. }
  201. pos--;
  202. }
  203. }*/
  204. pos++;
  205. Zelle->ribopos=pos;
  206. }
  207. // a nice funtion to generate BNA
  208. string MakeBNA() {
  209. string s="####";
  210. // for(int i=0; i<20; i++){
  211. while(rnd(10)){
  212. switch(rand()%10){
  213. case 0: s = s + "<"; break;
  214. case 1: s = s + ">"; break;
  215. case 2: s = s + "+"; break;
  216. case 3: s = s + "-"; break;
  217. case 4: s = s + "{"; break;
  218. case 5: s = s + "}"; break;
  219. case 6: s = s + "["; break;
  220. case 7: s = s + "]"; break;
  221. case 8: s = s + "."; break;
  222. case 9: s = s + ","; break;
  223. }
  224. }
  225. // cout<<s<<endl;
  226. return s;
  227. }
  228. // reset all values
  229. void init(){
  230. srand(time(0));
  231. for(int x=0; x<SIZEX; x++) {
  232. for(int y=0; y<SIZEY; y++) {
  233. Feld[x][y].x = x;
  234. Feld[x][y].y = y;
  235. for(int n=0; n<20; n++)
  236. Feld[x][y].feld[n] = 0;
  237. Feld[x][y].pfeld = 0;
  238. Feld[x][y].r = rand()%200 + 50;
  239. Feld[x][y].g = rand()%200 + 50;
  240. Feld[x][y].b = rand()%200 + 50;
  241. Feld[x][y].ZUP = 0;
  242. Feld[x][y].alive = false; //!rnd(9);
  243. Feld[x][y].ribopos = 0;
  244. Feld[x][y].BNA = MakeBNA();
  245. }
  246. }
  247. // experimental life generation functions ;)
  248. for(int x=0; x<20; x++) {
  249. for(int y=0; y<20; y++) {
  250. Feld[x][y].alive = rnd(2);
  251. }
  252. }
  253. Feld[80][80].alive = true; //!rnd(9);
  254. Feld[81][81].alive = true; //!rnd(9);
  255. Feld[79][81].alive = true; //!rnd(9);
  256. Feld[80][82].alive = true; //!rnd(9);
  257. Feld[80][80].BNA = "######.###{##{###.#######";
  258. Feld[81][81].BNA = "###########";
  259. Feld[79][81].BNA = "###########";
  260. Feld[80][82].BNA = "###########";
  261. }
  262. int main (int argc, char** argv)
  263. {
  264. // initialise a lot of uninteresting stuff
  265. init();
  266. bool done = false;
  267. SDL_Event event;
  268. SDL_Surface *screen;
  269. SDL_Init ( SDL_INIT_TIMER || SDL_INIT_VIDEO );
  270. screen = SDL_SetVideoMode(SIZEX*WIDTH, SIZEY*HEIGHT, 16, SDL_SWSURFACE);
  271. int showper = SHOWPER;
  272. while (!done)
  273. {
  274. while(SDL_PollEvent(&event))
  275. switch(event.type)
  276. {
  277. case SDL_KEYDOWN:
  278. if (event.key.keysym.sym==SDLK_F1) init(); // reset
  279. if (event.key.keysym.sym==SDLK_F2) dodeathfunc=!dodeathfunc;
  280. if (event.key.keysym.sym==SDLK_F4) showper = 0; // pause
  281. if (event.key.keysym.sym==SDLK_F5) showper = 1; // speed mod
  282. if (event.key.keysym.sym==SDLK_F6) showper = 100; //
  283. if (event.key.keysym.sym==SDLK_F7) showper = 1000; //
  284. if (event.key.keysym.sym==SDLK_F8) showper = 10000; //
  285. if (event.key.keysym.sym==SDLK_F9) mutarate = 1000; // speed mod
  286. if (event.key.keysym.sym==SDLK_F10) mutarate = 100; //
  287. if (event.key.keysym.sym==SDLK_F11) mutarate = 10; //
  288. if (event.key.keysym.sym==SDLK_F12) mutarate = 1; //
  289. if (event.key.keysym.sym==SDLK_ESCAPE) // quit
  290. done=true;
  291. break;
  292. };
  293. bool Feld2[SIZEX][SIZEY];
  294. for(int k=0; k<50; k++){
  295. // a game of life like death funtion
  296. if(dodeathfunc) {
  297. for(int x=0; x<SIZEX; x++) {
  298. for(int y=0; y<SIZEY; y++) {
  299. int c = (int)Feld[x+1][y+1].alive +
  300. (int)Feld[x+1][y-1].alive +
  301. (int)Feld[x-1][y-1].alive +
  302. (int)Feld[x ][y-1].alive +
  303. (int)Feld[x ][y+1 ].alive +
  304. (int)Feld[x-1][y+1].alive +
  305. (int)Feld[x+1][y ].alive +
  306. (int)Feld[x-1][y ].alive;
  307. //if(c >= 2 && c <= 5) Feld2[x][y] = true;
  308. // else Feld2[x][y] = false;
  309. c = 8 - c;
  310. if (c < 2) Feld2[x][y] = false;
  311. Feld[x][y].resswert = c;
  312. }
  313. }
  314. for(int x=0; x<SIZEX; x++) {
  315. for(int y=0; y<SIZEY; y++) {
  316. if(!Feld2[x][y]) Feld[x][y].alive=false;
  317. }
  318. }
  319. }
  320. // calc 'em
  321. for(int i=0; i<showper; i++) {
  322. int x=rand()%SIZEX; int y=rand()%SIZEY;
  323. if(Feld[x][y].alive) {
  324. //for(int n=0; n<20; n++)
  325. // Feld[x][y].feld[n] = 0;
  326. BrainFuck(&Feld[x][y]);
  327. }
  328. }
  329. }
  330. // show 'em
  331. show(screen);
  332. //SDL_Delay(50);
  333. };
  334. // quit 'em
  335. SDL_Quit();
  336. return 0;
  337. }