xstoneage.c 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463
  1. /***************************************************************************
  2. * *
  3. * This program is free software; you can redistribute it and/or modify *
  4. * it under the terms of the GNU General Public License as published by *
  5. * the Free Software Foundation; either version 2 of the License, or *
  6. * (at your option) any later version. *
  7. * *
  8. ***************************************************************************/
  9. /*** xstoneage, stoneage for linux by bzt 2003 ***/
  10. // Here goes the main stuff
  11. // intro, menu, setup and the game itself
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <signal.h>
  15. #include <sys/stat.h>
  16. #include <time.h>
  17. #include <dirent.h>
  18. #include <X11/Xlib.h>
  19. #include <X11/Xutil.h>
  20. #include <X11/Xos.h>
  21. #include <X11/Xatom.h>
  22. #include <X11/keysym.h>
  23. #include <X11/Intrinsic.h>
  24. #include <X11/cursorfont.h>
  25. #include <zlib.h>
  26. #include "xinit.h"
  27. //load a tga file
  28. XImage *loadtga(gzFile gf);
  29. //level editor
  30. void editor();
  31. //intro, menu and setup images
  32. XImage *stoneage;
  33. XImage *menu;
  34. XImage *light;
  35. XImage *pass;
  36. XImage *hiscore;
  37. XImage *endseq;
  38. XImage *fonts;
  39. XImage *fonts2;
  40. XImage *pauseimg;
  41. XImage *ximage;
  42. //images in game
  43. XImage *bgr;
  44. XImage *temp;
  45. //items in game
  46. XImage *tiles;
  47. XImage *sidebars;
  48. XImage *eyes;
  49. XImage *dragon;
  50. level levelmap;
  51. unsigned char candles,lightgame;
  52. unsigned int score,oldscore;
  53. //other variables
  54. int alt_pressed=FALSE;
  55. int control_pressed=FALSE;
  56. int mousebutton_pressed=FALSE;
  57. int mousex,mousey,mdx,mdy;
  58. int i,mode;
  59. char cfgfile[512];
  60. char scorefile[256];
  61. int status,childpid,musicpid=0;
  62. int timecnt, curr,selcurr,oldcurr,drag,anim,transposrting;
  63. int olddrag,traveling,move, mtile, moving, movepix,mx,my,transporting;
  64. int entering, leaving;
  65. int redkey=0,greenkey=0;
  66. int codeptr;
  67. int rotateeye=0,rotcnt=0,drot=1;
  68. hscoretype hiscores[9];
  69. int mask[12]={3,0,1,4,1,5,9,2,6,5,3,5};
  70. byte eyepos[220]={
  71. 2,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,5,6,6,6,
  72. 2,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,6,6,6,6,
  73. 2,2,2,2,2,2,2,3,3,3,3,3,4,4,5,5,6,6,6,7,
  74. 2,2,2,2,2,2,2,3,3,3,3,3,4,4,5,5,6,6,7,7,
  75. 2,2,2,2,2,2,2,2,3,3,3,3,4,4,5,5,6,6,7,7,
  76. 2,2,2,2,2,2,2,2,2,3,3,3,4,4,5,6,6,6,7,7,
  77. 2,2,2,2,2,2,2,2,2,2,3,3,4,4,5,6,6,7,7,7,
  78. 1,2,2,2,2,2,2,2,2,2,3,3,4,4,5,6,7,7,7,7,
  79. 1,1,1,2,2,2,2,2,2,2,2,3,4,5,6,6,7,7,7,7,
  80. 1,1,1,1,1,1,2,2,2,2,2,3,4,5,6,7,7,7,8,8
  81. };
  82. /**
  83. * start the game
  84. */
  85. int startgame()
  86. {
  87. fadeimage(FADEOUT,0,0,ximage);
  88. strcpy(levelmap.nextlink,"SRTLEV");
  89. score=0; candles=lightgame?10:5;
  90. dothegame();
  91. CopyImage(0, ximage, 0, 0, menu, 0, 0, menu->width, menu->height);
  92. fadeimage(FADEIN,0,0,ximage); XFlush(dis);
  93. mousex=1024;
  94. }
  95. /**
  96. * enter query password mode
  97. */
  98. int getcode()
  99. {
  100. fadeimage(FADEOUT,0,0,ximage);
  101. CopyImage(0, ximage, 0, 0, pass, 0, 0, pass->width, pass->height);
  102. fadeimage(FADEIN,0,0,ximage);
  103. mode=2;
  104. levelmap.nextlink[0]=0; codeptr=0;
  105. }
  106. /**
  107. * display hi scores
  108. */
  109. int doscores()
  110. {
  111. fadeimage(FADEOUT,0,0,ximage);
  112. displayhiscore();
  113. CopyImage(0, ximage, 0, 0, menu, 0, 0, menu->width, menu->height);
  114. fadeimage(FADEIN,0,0,ximage); XFlush(dis);
  115. }
  116. /**
  117. * toggle difficulty level
  118. */
  119. int dodifficulty()
  120. {
  121. CopyImage(0, ximage, 435, 100, menu, 435, 100, light->width, light->height);
  122. lightgame^=1;
  123. if(lightgame) CopyImage(1,ximage,435,100, light, 0,0, light->width,light->height);
  124. XPutImage(dis, win, gc, ximage, 435, 100, 435, 100, light->width, light->height);
  125. XSync(dis,FALSE);
  126. }
  127. /**
  128. * invoke level editor
  129. */
  130. int doeditor()
  131. {
  132. fadeimage(FADEOUT,0,0,ximage);
  133. XResizeWindow(dis,win,740,400);
  134. editor();
  135. XResizeWindow(dis,win,640,400);
  136. CopyImage(0, ximage, 0, 0, menu, 0, 0, menu->width, menu->height);
  137. fadeimage(FADEIN,0,0,ximage); XFlush(dis);
  138. }
  139. /**
  140. * program end, close display, store unsaved files etc.
  141. */
  142. void byez(){
  143. fadeimage(FADEOUT,0,0,ximage);
  144. closedisplay();
  145. savescorefile();
  146. #if DEBUG==TRUE
  147. printf("Exiting program.\n");
  148. #else
  149. printf("\nDeveloped by bzt after the old DOS game, Stone Age\n"
  150. "Thanks to:\nMr.Break - idea, levels\n"
  151. "And, at last but not at least, my girlfriend's patience, who lacked me a lot\n"
  152. "while I was programming. And thanks for the coffees and food!\n");
  153. #endif
  154. fflush(stdout);
  155. exit(0);
  156. }
  157. /**
  158. * load hi scores
  159. */
  160. void loadscorefile(){
  161. int f; int i; int j;
  162. //default values
  163. for(i=0;i<9;i++) {
  164. hiscores[i].score=32<<(9-i);
  165. hiscores[i].level=9-i;
  166. strcpy((char*)&hiscores[i].name,i%3==0?"BZT":(i%3==1?"MR.BREAK":"SZISZI"));
  167. }
  168. //load
  169. f=open("/var/games/xstoneage/hiscores",O_RDONLY);
  170. if(f>2){
  171. for(i=0;i<9;i++){
  172. hiscores[i].score=0; read(f,&hiscores[i].score,3); hiscores[i].score^=(i+i*256+i*65536);
  173. hiscores[i].level=0; read(f,&hiscores[i].level,1); hiscores[i].level^=i;
  174. read(f,&hiscores[i].name,12);
  175. for(j=0;j<12;j++){
  176. hiscores[i].name[j]^=i+mask[j]+0x20;
  177. }
  178. }
  179. close(f);
  180. }
  181. }
  182. /**
  183. * save hi scores
  184. */
  185. void savescorefile(void){
  186. int f; int i; int j;
  187. #if DEBUG==TRUE
  188. printf("Saving hiscores.\n");
  189. #endif
  190. mkdir("/var/games",RIGHTS(7,5,5));
  191. mkdir("/var/games/xstoneage",RIGHTS(7,5,5));
  192. f=open("/var/games/xstoneage/hiscores",O_WRONLY | O_CREAT,RIGHTS(6,4,4));
  193. if(f>2){
  194. for(i=0;i<9;i++){
  195. hiscores[i].score^=(i+i*256+i*65536);
  196. write(f,&hiscores[i].score,3);
  197. hiscores[i].level^=i;
  198. write(f,&hiscores[i].level,1);
  199. for(j=0;j<12;j++){
  200. hiscores[i].name[j]^=i+mask[j]+0x20;
  201. }
  202. write(f,&hiscores[i].name,12);
  203. }
  204. close(f);
  205. }
  206. }
  207. /**
  208. * Create an empty screen
  209. */
  210. XImage *CreateEmptyImage()
  211. {
  212. byte *data;
  213. XImage *ximage;
  214. ximage = XCreateImage(dis, vsl, 24, ZPixmap, 0, NULL, 640, 400, 8, 640 * 4);
  215. data= (byte *) malloc(((640 * 480)) * 4);
  216. bzero(data,(640 * 480) * 4);
  217. ximage->data= (char *)data;
  218. ximage->byte_order= MSBFirst;
  219. ximage->bits_per_pixel=24;
  220. return(ximage);
  221. }
  222. /**
  223. * create an image with scrolling test on it
  224. */
  225. int drawscroll(XImage *ximage, XImage *bg,int x, int y, char *txt){
  226. int i,dx,dy;
  227. char c;
  228. dx=x; dy=y;
  229. for(i=0;i<strlen(txt);i++){
  230. if(txt[i]!='\n'){
  231. if(dy>=-32){
  232. c=txt[i];
  233. if(c!='_'){
  234. if(c==' ') c='-';
  235. if(c=='!') c='/';
  236. CopyImage(0, ximage, dx, dy, bg, dx, dy,32,34);
  237. CopyImage(1, ximage, dx, dy, fonts2, (c-',')*32, 0,32,32);
  238. }
  239. dx+=32;
  240. if(dx>=640){ dx=x; dy+=34;}
  241. }
  242. } else {
  243. dx=x;
  244. dy+=34;
  245. }
  246. if(dy>ximage->height) i=strlen(txt);
  247. }
  248. }
  249. /**
  250. * draw a number with pixmap font
  251. */
  252. int drawnum(XImage *ximage,int x, int y, int num){
  253. char txt[16];
  254. int i;
  255. sprintf(txt,"%d",num);
  256. for(i=0;i<strlen(txt);i++){
  257. CopyImage(1, ximage, x-(strlen(txt)-i)*16, y, fonts, (txt[i]-'0')*16, 34,16,16);
  258. }
  259. }
  260. /**
  261. * draw a text with pixmap font
  262. */
  263. int drawtext(XImage *ximage,int x, int y, char *txt){
  264. int i,dx,dy;
  265. char c;
  266. dx=x; dy=y;
  267. for(i=0;i<strlen(txt);i++){
  268. if(txt[i]!='\n'){
  269. c=txt[i];
  270. if(c!='_'){
  271. if(c==' ') c='-';
  272. if(c=='!') c='/';
  273. CopyImage(1, ximage, dx, dy, fonts2, (c-',')*32, 0,32,32);
  274. }
  275. dx+=32;
  276. if(dx>=640){ dx=x; dy+=34;}
  277. } else {
  278. dx=x;
  279. dy+=34;
  280. }
  281. if(dy>ximage->height) i=strlen(txt);
  282. }
  283. }
  284. /**
  285. * read next level
  286. */
  287. int readlevel(){
  288. DIR *dh;
  289. struct dirent *de;
  290. unsigned char str[512];
  291. int path;
  292. int i,j,found;
  293. byte b;
  294. found=0;
  295. #if DEBUG==TRUE
  296. printf("readlevel %s\n",levelmap.nextlink); fflush(stdout);
  297. #endif
  298. if(strcmp(levelmap.nextlink,"ENDSEQ")==0){
  299. CopyImage(0,ximage,0,0,endseq,0,0,endseq->width,endseq->height);
  300. fadeimage(FADEIN,0,0,ximage);
  301. strcpy(str,"_<CONGRATULATIONS!>\n\n\n_<YOU HAVE MADE IT>\n\n_<YOU HAVE REACHED>\n___<THE EXIT !!!>");
  302. path=0; i=0;
  303. report.type=None;
  304. while(report.type!=KeyPress && report.type!=ButtonRelease){
  305. if(XPending(dis)) XNextEvent(dis, &report);
  306. //scroll text
  307. if(i<=300){
  308. drawscroll(ximage,endseq,0,ximage->height-i,(char *)&str);
  309. XPutImage(dis, win, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
  310. XSync(dis,FALSE);
  311. }
  312. if(i==350) CopyImage(0,ximage,0,0,endseq,0,0,endseq->width,endseq->height);
  313. //fade out background
  314. if(i>=350 && i<366){
  315. if(i%2==0){
  316. for(j=0;j<ximage->bytes_per_line*ximage->height;j++){
  317. b=memToVal(ximage->data+j,1); b=b/2;
  318. valToMem(b,ximage->data+j,1);
  319. }
  320. drawtext(ximage,0,100,(char*)&str);
  321. XPutImage(dis, win, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
  322. XSync(dis,FALSE);
  323. }
  324. }
  325. //fade congrat text
  326. if(i>=500 && i<516){
  327. if(i%2==0){
  328. for(j=0;j<ximage->bytes_per_line*ximage->height;j++){
  329. b=memToVal(ximage->data+j,1); b=b/2;
  330. valToMem(b,ximage->data+j,1);
  331. }
  332. XPutImage(dis, win, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
  333. XSync(dis,FALSE);
  334. }
  335. }
  336. //message #1
  337. if(i==520){
  338. strcpy(str,"_<REMADE AFTER THE>_\n\n__< OLD DOS GAME >_\n\n_<BY ECLIPSE @1992>");
  339. drawtext(ximage,0,100,(char*)&str);
  340. fadeimage(FADEIN,0,0,ximage);
  341. }
  342. //message #2
  343. if(i==620){
  344. fadeimage(FADEOUT,0,0,ximage);
  345. for(j=0;j<ximage->bytes_per_line*ximage->height;j++) valToMem(0,ximage->data+j,1);
  346. strcpy(str,"__< IDEA:MR.BREAK=>\n__<=CODE:BZT >\n\n< LEVELS:MR.BREAK=>_______<@ BZT >");
  347. drawtext(ximage,0,100,(char*)&str);
  348. fadeimage(FADEIN,0,0,ximage);
  349. }
  350. //message #3
  351. if(i==720){
  352. fadeimage(FADEOUT,0,0,ximage);
  353. for(j=0;j<ximage->bytes_per_line*ximage->height;j++) valToMem(0,ximage->data+j,1);
  354. strcpy(str,"__<THANKS PLAYING>\n\n<= THIS FREE GAME @>\n\n__<=HOPE YOU HAVE>\n\n___< ENJOYED IT@>");
  355. drawtext(ximage,0,100,(char*)&str);
  356. fadeimage(FADEIN,0,0,ximage);
  357. }
  358. //message #4
  359. if(i==820){
  360. fadeimage(FADEOUT,0,0,ximage);
  361. for(j=0;j<ximage->bytes_per_line*ximage->height;j++) valToMem(0,ximage->data+j,1);
  362. strcpy(str,"_< LIVE FREE, USE >\n\n___<= LINUX @>\n\n__<FREE SOFTWARE>\n\n____<@FOREVER!=>");
  363. drawtext(ximage,0,100,(char*)&str);
  364. fadeimage(FADEIN,0,0,ximage);
  365. }
  366. //message #5
  367. if(i==920){
  368. fadeimage(FADEOUT,0,0,ximage);
  369. for(j=0;j<ximage->bytes_per_line*ximage->height;j++) valToMem(0,ximage->data+j,1);
  370. strcpy(str,"<STONEAGE FOR LINUX>\n\n__< 2003@ GPL >");
  371. drawtext(ximage,0,100,(char*)&str);
  372. fadeimage(FADEIN,0,0,ximage);
  373. }
  374. //if a key pressed, stop end sequence
  375. i++; if(i>1020) report.type=KeyPress;
  376. usleep(i<350?10000:50000);
  377. }
  378. fadeimage(FADEOUT,0,0,ximage);
  379. } else {
  380. //look up level in pak
  381. for(i=0;i<numlevels;i++){
  382. if(strncmp(levelmap.nextlink,levels[i].code,6)==0){
  383. memcpy(&levelmap,&levels[i],sizeof(level));
  384. found=1; i=numlevels;
  385. }
  386. }
  387. //look up user defined level
  388. if(found==0){
  389. //search files
  390. strcpy(str,getenv("HOME"));
  391. strcat(str,"/.xstoneage/");
  392. path=strlen(str);
  393. dh=opendir(str);
  394. strcat(str,levelmap.nextlink);
  395. strcat(str,".map");
  396. #if DEBUG==TRUE
  397. printf("File: %s\n",str); fflush(stdout);
  398. #endif
  399. de=readdir(dh);
  400. while(de!=NULL){
  401. if(!strncmp(de->d_name,str + path,10)){
  402. i=open(str,O_RDONLY);
  403. read(i,&levelmap,sizeof(level));
  404. close(i);
  405. found=1;
  406. break;
  407. }
  408. de=readdir(dh);
  409. };
  410. closedir(dh);
  411. }
  412. //level not found
  413. if(found==0){
  414. temp=CreateEmptyImage();
  415. sprintf(str,"\n\n<SORRY, BUT YOU DO>\n"
  416. "NOT FIND THE CHAMBER__<WHICH NAME WAS:>\n\n"
  417. "____<@ %s =>",
  418. levelmap.nextlink);
  419. drawtext(temp,0,0,(char*)&str);
  420. fadeimage(FADEINOUT,0,0,temp);
  421. DestroyImage(temp);
  422. return(0);
  423. }
  424. }
  425. //if level found
  426. if(found){
  427. temp=CreateEmptyImage();
  428. drawtext(temp,0,0,"\n\n_<YOU ARE ABOUT TO>\n"
  429. "= ENTER NEXT LEVEL.>\n\n\n"
  430. "__<PRESS ANY KEY>\n"
  431. "__<@IF YOU THINK>\n"
  432. "<; YOU ARE READY =>");
  433. fadeimage(FADEINOUT,0,0,temp);
  434. DestroyImage(temp);
  435. }
  436. return(found);
  437. }
  438. /**
  439. * display the hi scroes
  440. */
  441. void displayhiscore(){
  442. int i; char number[8];
  443. CopyImage(0,ximage,0,0,hiscore,0,0,hiscore->width,hiscore->height);
  444. for(i=0;i<9;i++){
  445. if(hiscores[i].score!=0){
  446. if(score==hiscores[i].score) {
  447. drawtext(ximage,0,i*34+74," ");
  448. score=0;
  449. }
  450. sprintf(number,"%6d",hiscores[i].score);
  451. drawtext(ximage,10,i*34+74,(char*)&hiscores[i].name);
  452. drawtext(ximage,630-strlen(number)*32,i*34+74,(char*)&number);
  453. }
  454. }
  455. fadeimage(FADEINOUT,0,0,ximage);
  456. }
  457. /**
  458. * build scene
  459. */
  460. void CreateScene(){
  461. int i,j,tmp;
  462. //scene
  463. for(i=0;i<ximage->height;i++) for(j=0;j<ximage->width;j++) XPutPixel(ximage,j,i,0);
  464. for(i=0;i<11;i++){
  465. for(j=0;j<20;j++){
  466. tmp=levelmap.map[i*20+j];
  467. if(tmp==0xff) {
  468. CopyImage(0, ximage, j*32, i*32, bgr, levelmap.tileset*640+j*32, levelmap.background*352+i*32, 32, 32);
  469. } else {
  470. CopyImage(0, ximage, j*32, i*32, tiles, (tmp/3)*32, (tmp%3)*32+levelmap.tileset*96,32,32);
  471. }
  472. }
  473. }
  474. CopyImage(0, ximage, 0, 355, sidebars, 0, levelmap.sidebar*45,640,45);
  475. drawnum(ximage, 95,370, timecnt);
  476. drawnum(ximage, 289,370, score);
  477. drawnum(ximage, 530,370, greenkey);
  478. drawnum(ximage, 630,370, redkey);
  479. if(eyepos[drag]<5) i=0; else i=26;
  480. j=42;
  481. if(eyepos[drag]==2 || eyepos[drag]==7) j=28;
  482. if(eyepos[drag]==3 || eyepos[drag]==6) j=14;
  483. if(eyepos[drag]==4 || eyepos[drag]==5) j=0;
  484. CopyImage(0, ximage, 420, 362, eyes, i, j,26,14);
  485. }
  486. /**
  487. * display screen from ximage buffer
  488. */
  489. void exposehandler(){
  490. int dx,dy;
  491. //add dragon
  492. if(!moving && !traveling && !transporting && !entering && !leaving)
  493. CopyImage(1,ximage, (drag%20)*32, (drag/20)*32, dragon, 0, 0, 32, 32);
  494. //add sidebar and counters
  495. CopyImage(0, ximage, 0, 370, sidebars, 0, levelmap.sidebar*45+15,640,16);
  496. drawnum(ximage, 95,370, timecnt);
  497. drawnum(ximage, 289,370, score);
  498. drawnum(ximage, 530,370, greenkey);
  499. drawnum(ximage, 630,370, redkey);
  500. //add eye balls
  501. if(eyepos[drag]<5) dx=0; else dx=26;
  502. dy=42;
  503. if(eyepos[drag]==2 || eyepos[drag]==7) dy=28;
  504. if(eyepos[drag]==3 || eyepos[drag]==6) dy=14;
  505. if(eyepos[drag]==4 || eyepos[drag]==5) dy=0;
  506. CopyImage(0, ximage, 420, 362, eyes, dx, dy,26,14);
  507. //display
  508. XPutImage(dis, win, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
  509. XSync(dis,FALSE);
  510. fflush(stdout);
  511. //delay
  512. usleep(10000);
  513. }
  514. /**
  515. * start game choosen from menu
  516. */
  517. void dothegame(){
  518. char duma[512],c;
  519. int i,j,exitgame=3,worth,dx,dy;
  520. time_t oldt,newt;
  521. redkey=0; greenkey=0;
  522. traveling=0; moving=0; transporting=0;
  523. movepix=0;
  524. //start background music
  525. musicpid=fork();
  526. if(musicpid==0){
  527. i=open("/usr/lib/xstoneage/music.mp3",O_RDONLY);
  528. if(i<3) {
  529. printf("Music file not found, no music.\n"); fflush(stdout);
  530. exit(1);
  531. } else {
  532. close(i);
  533. system("mpg123 -q -Z /usr/lib/xstoneage/music.mp3");
  534. }
  535. exit(0);
  536. }
  537. //main loop for a level
  538. while(exitgame!=2){
  539. //failsafe
  540. if(exitgame==3) if(readlevel()==0) break;
  541. timecnt=levelmap.soltime*(lightgame+1);
  542. //calculate score for a level
  543. worth=0;
  544. for(i=0;i<220;i++){
  545. if(levelmap.map[i]==13){ drag=i; i=220;}
  546. if(levelmap.map[i]==11) worth+=2; //disapear
  547. if(levelmap.map[i]==15) worth+=5; //locks
  548. if(levelmap.map[i]==18) worth+=5;
  549. if(levelmap.map[i]==22) worth+=5; //transport
  550. if(levelmap.map[i]==24) worth+=2; //left
  551. if(levelmap.map[i]==25) worth+=2; //right
  552. if(levelmap.map[i]==27) worth+=2; //up
  553. if(levelmap.map[i]==28) worth+=2; //down
  554. if(levelmap.map[i]==30) worth+=3; //left-right
  555. if(levelmap.map[i]==31) worth+=3; //up-down
  556. if(levelmap.map[i]==32) worth+=4; //all directions
  557. if(levelmap.map[i]<=10) worth+=1; //standard items
  558. }
  559. //build up scene
  560. CreateScene();
  561. fadeimage(FADEIN,0,0,ximage);
  562. anim=0; curr=0xff; selcurr=0xff; oldcurr=0xff;
  563. entering=1; movepix=8; exposehandler();
  564. exitgame=0;
  565. //main game loop on a given level
  566. while (!exitgame) {
  567. //update eyes
  568. if(rotateeye){
  569. if(rotcnt<5) dx=0; else dx=26;
  570. dy=42;
  571. if(rotcnt==2 || rotcnt==7) dy=28;
  572. if(rotcnt==3 || rotcnt==6) dy=14;
  573. if(rotcnt==4 || rotcnt==5) dy=0;
  574. rotcnt+=drot; if(rotcnt>8) drot=-1; if(rotcnt<1) drot=1;
  575. CopyImage(0, ximage, 420, 362, eyes, dx, dy,26,14);
  576. XPutImage(dis, win, gc, ximage, 420, 362, 420, 362,26,14);
  577. timecnt=levelmap.soltime*(lightgame+1);
  578. }
  579. //get remaining time
  580. newt=time(NULL);
  581. if(newt!=oldt && !entering && !leaving) {
  582. timecnt--; oldt=newt;
  583. if(!moving && !traveling && !transporting && !entering){
  584. if(!moving && !traveling && !transporting && !entering && !leaving){
  585. CopyImage(0, ximage,
  586. (drag%20)*32, (drag/20)*32,
  587. bgr,
  588. levelmap.tileset*640+(drag%20)*32, levelmap.background*352+(drag/20)*32,
  589. 32, 32);
  590. if(levelmap.map[drag]!=0xff)
  591. CopyImage(1,ximage,
  592. (drag%20)*32, (drag/20)*32,
  593. tiles,
  594. (levelmap.map[drag]/3)*32, (levelmap.map[drag]%3)*32+levelmap.tileset*96,
  595. 32, 32);
  596. CopyImage(1,ximage, (drag%20)*32, (drag/20)*32, dragon, 0, 0, 32, 32);
  597. XPutImage(dis, win, gc, ximage,
  598. (drag%20)*32, (drag/20)*32, (drag%20)*32, (drag/20)*32,
  599. 33, 33);
  600. }
  601. CopyImage(0, ximage, 0, 370, sidebars, 0, levelmap.sidebar*45+15,96,16);
  602. drawnum(ximage, 95,370, timecnt);
  603. XPutImage(dis, win, gc, ximage, 0, 370, 0, 370, 96, 16);
  604. XFlush(dis);
  605. }
  606. }
  607. //slow down entering and leaving animations
  608. if(entering || leaving) usleep(50000);
  609. //when run out of time
  610. if(timecnt==0) { exitgame=1; candles--; if(candles==0) exitgame=2; break; }
  611. usleep(10000);
  612. report.type=None;
  613. //when not in animation
  614. if(!moving && !traveling && !transporting && !entering && !leaving){
  615. if(XPending(dis)) XNextEvent(dis, &report);
  616. //handle events
  617. switch (report.type) {
  618. case ButtonPress:
  619. #if DEBUG==TRUE
  620. printf("Mouse button pressed at %d %d.\n",report.xbutton.x,report.xbutton.y);
  621. #endif
  622. mousebutton_pressed=TRUE;
  623. mousex=report.xbutton.x;
  624. mousey=report.xbutton.y;
  625. //cheat
  626. if (mousex>=420 && mousey>=362 &&
  627. mousex<=446 && mousey<=376 &&
  628. alt_pressed==TRUE && control_pressed==TRUE) {
  629. rotateeye=1;
  630. timecnt=levelmap.soltime*(lightgame+1);
  631. if(lightgame) i=10; else i=5;
  632. candles=i;
  633. score=0;
  634. printf("Cheat enabled. New time: %d, candles: %d. Score 0.\n",timecnt,candles);
  635. oldt=newt=time(NULL);
  636. exposehandler();
  637. }
  638. break;
  639. case ButtonRelease:
  640. #if DEBUG==TRUE
  641. printf("Mouse button released at %d %d.\n",report.xbutton.x,report.xbutton.y);
  642. #endif
  643. mousebutton_pressed=FALSE;
  644. if (mousex>=420 && mousey>=362 && mousex<=446 && mousey<=376) {
  645. rotateeye=0;
  646. timecnt=levelmap.soltime*(lightgame+1);
  647. exposehandler();
  648. }
  649. if (mousex>=0 && mousey>=0 && mousex<=640 && mousey<=352) {
  650. if(report.xbutton.button==3) curr=0xff; else {
  651. curr=(mousey/32*20)+(mousex/32);
  652. if( levelmap.map[curr]!=24 &&
  653. levelmap.map[curr]!=25 &&
  654. levelmap.map[curr]!=27 &&
  655. levelmap.map[curr]!=28 &&
  656. levelmap.map[curr]!=30 &&
  657. levelmap.map[curr]!=31 &&
  658. levelmap.map[curr]!=32) curr=0xff;
  659. }
  660. if(curr==drag) curr=0xff;
  661. selcurr=oldcurr=0xff;
  662. exposehandler();
  663. }
  664. break;
  665. case ResizeRequest:
  666. #if DEBUG==TRUE
  667. printf("I have been resized.\n");
  668. #endif
  669. XSetForeground(dis, gc, BlackPixel(dis,0)); XClearWindow(dis,win);
  670. exposehandler();
  671. break;
  672. case Expose:
  673. #if DEBUG==TRUE
  674. printf("I have been exposed.\n");
  675. #endif
  676. exposehandler();
  677. break;
  678. case KeyPress:
  679. #if DEBUG==TRUE
  680. printf("keypress: %X\n",XLookupKeysym(&report.xkey, 0));
  681. #endif
  682. if (XLookupKeysym(&report.xkey, 0) == XK_Alt_R ||
  683. XLookupKeysym(&report.xkey, 0) == XK_Alt_L) {
  684. alt_pressed=TRUE;
  685. }
  686. if (XLookupKeysym(&report.xkey, 0) == XK_Control_R ||
  687. XLookupKeysym(&report.xkey, 0) == XK_Control_L) {
  688. control_pressed=TRUE;
  689. }
  690. oldcurr=selcurr;
  691. if (XLookupKeysym(&report.xkey, 0) == XK_Escape) {
  692. exitgame=2;
  693. }
  694. if (XLookupKeysym(&report.xkey, 0) == XK_BackSpace) {
  695. exitgame=1; candles--; if(candles==0) exitgame=2;
  696. }
  697. if (XLookupKeysym(&report.xkey, 0) == XK_Tab) {
  698. CreateScene();
  699. exposehandler();
  700. }
  701. if (XLookupKeysym(&report.xkey, 0) == XK_Return) {
  702. curr=selcurr;
  703. if( levelmap.map[curr]!=24 &&
  704. levelmap.map[curr]!=25 &&
  705. levelmap.map[curr]!=27 &&
  706. levelmap.map[curr]!=28 &&
  707. levelmap.map[curr]!=30 &&
  708. levelmap.map[curr]!=31 &&
  709. levelmap.map[curr]!=32) curr=0xff;
  710. selcurr=oldcurr=0xff;
  711. exposehandler();
  712. }
  713. if (XLookupKeysym(&report.xkey, 0) == XK_space) {
  714. curr=0xff;
  715. if(selcurr==0xff) selcurr=drag; else selcurr=0xff;
  716. exposehandler();
  717. }
  718. if (XLookupKeysym(&report.xkey, 0) == XK_Left) {
  719. if(selcurr!=0xff){
  720. if(selcurr%20>0) selcurr--;
  721. }else{
  722. olddrag=drag;
  723. if(curr!=0xff){
  724. if(levelmap.map[curr]==24 || levelmap.map[curr]==31 || levelmap.map[curr]==32){
  725. move=curr; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=1; }
  726. } else {
  727. if(drag%20>0 && levelmap.map[drag-1]==0xff &&
  728. (levelmap.map[drag]==24 || levelmap.map[drag]==31 || levelmap.map[drag]==32)){
  729. move=drag; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=1;
  730. }
  731. if(drag%20>0 && levelmap.map[drag-1]>9 &&
  732. levelmap.map[drag-1]!=14 && levelmap.map[drag-1]!=17 &&
  733. levelmap.map[drag-1]!=20 && levelmap.map[drag-1]!=23 &&
  734. levelmap.map[drag-1]!=26 && levelmap.map[drag-1]!=29 &&
  735. levelmap.map[drag-1]!=0xff) {
  736. traveling=1; movepix=32; drag--;
  737. }
  738. }
  739. if(!traveling && !moving && levelmap.map[drag]==22) {
  740. olddrag=drag;
  741. drag++; if(drag>220) drag=0;
  742. while(levelmap.map[drag]!=22) {drag++; if(drag>220) drag=0;}
  743. transporting=1; movepix=7;
  744. }
  745. }
  746. }
  747. if (XLookupKeysym(&report.xkey, 0) == XK_Right) {
  748. if(selcurr!=0xff){
  749. if(selcurr%20<19) selcurr++;
  750. }else{
  751. olddrag=drag;
  752. if(curr!=0xff){
  753. if(levelmap.map[curr]==25 || levelmap.map[curr]==31 || levelmap.map[curr]==32){
  754. move=curr; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=2; }
  755. } else {
  756. if(drag%20<19 && levelmap.map[drag+1]==0xff &&
  757. (levelmap.map[drag]==25 || levelmap.map[drag]==31 || levelmap.map[drag]==32)){
  758. move=drag; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=2;
  759. }
  760. if(drag%20<19 && levelmap.map[drag+1]>9 &&
  761. levelmap.map[drag+1]!=14 && levelmap.map[drag+1]!=17 &&
  762. levelmap.map[drag+1]!=20 && levelmap.map[drag+1]!=23 &&
  763. levelmap.map[drag+1]!=26 && levelmap.map[drag+1]!=29 &&
  764. levelmap.map[drag+1]!=0xff) {
  765. traveling=2; movepix=32; olddrag=drag; drag++;
  766. }
  767. }
  768. if(!traveling && !moving && levelmap.map[drag]==22) {
  769. olddrag=drag;
  770. drag++; if(drag>220) drag=0;
  771. while(levelmap.map[drag]!=22) {drag++; if(drag>220) drag=0; }
  772. transporting=1; movepix=7;
  773. }
  774. }
  775. }
  776. if (XLookupKeysym(&report.xkey, 0) == XK_Up) {
  777. if(selcurr!=0xff){
  778. if(selcurr>=20) selcurr-=20;
  779. }else{
  780. olddrag=drag;
  781. if(curr!=0xff){
  782. if(levelmap.map[curr]==27 || levelmap.map[curr]==30 || levelmap.map[curr]==32){
  783. move=curr; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=3; }
  784. } else {
  785. if(drag>=20 && levelmap.map[drag-20]==0xff &&
  786. (levelmap.map[drag]==27 || levelmap.map[drag]==30 || levelmap.map[drag]==32)){
  787. move=drag; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=3;
  788. }
  789. if(drag>=20 && levelmap.map[drag-20]>9 &&
  790. levelmap.map[drag-20]!=14 && levelmap.map[drag-20]!=17 &&
  791. levelmap.map[drag-20]!=20 && levelmap.map[drag-20]!=23 &&
  792. levelmap.map[drag-20]!=26 && levelmap.map[drag-20]!=29 &&
  793. levelmap.map[drag-20]!=0xff) {
  794. traveling=3; movepix=32; olddrag=drag; drag-=20;
  795. }
  796. }
  797. if(!traveling && !moving && levelmap.map[drag]==22) {
  798. olddrag=drag;
  799. drag++; if(drag>220) drag=0;
  800. while(levelmap.map[drag]!=22) {drag++; if(drag>220) drag=0;}
  801. transporting=1; movepix=7;
  802. }
  803. }
  804. }
  805. if (XLookupKeysym(&report.xkey, 0) == XK_Down) {
  806. if(selcurr!=0xff){
  807. if(selcurr<=200) selcurr+=20;
  808. }else{
  809. olddrag=drag;
  810. if(curr!=0xff){
  811. if(levelmap.map[curr]==28 || levelmap.map[curr]==30 || levelmap.map[curr]==32){
  812. move=curr; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=4; }
  813. } else {
  814. if(drag<=200 && levelmap.map[drag+20]==0xff &&
  815. (levelmap.map[drag]==28 || levelmap.map[drag]==30 || levelmap.map[drag]==32)){
  816. move=drag; mtile=levelmap.map[move]; levelmap.map[move]=0xff; moving=4;
  817. }
  818. if(drag<=200 && levelmap.map[drag+20]>9 &&
  819. levelmap.map[drag+20]!=14 && levelmap.map[drag+20]!=17 &&
  820. levelmap.map[drag+20]!=20 && levelmap.map[drag+20]!=23 &&
  821. levelmap.map[drag+20]!=26 && levelmap.map[drag+20]!=29 &&
  822. levelmap.map[drag+20]!=0xff) {
  823. traveling=4; movepix=32; olddrag=drag; drag+=20;
  824. }
  825. }
  826. if(!traveling && !moving && levelmap.map[drag]==22) {
  827. olddrag=drag;
  828. drag++; if(drag>220) drag=0;
  829. while(levelmap.map[drag]!=22) {drag++; if(drag>220) drag=0; }
  830. transporting=1; movepix=7;
  831. }
  832. }
  833. }
  834. if (XLookupKeysym(&report.xkey, 0) == XK_p) {
  835. dopause(320-pauseimg->width/2,180-pauseimg->height/2,45,pauseimg,ximage);
  836. }
  837. break;
  838. case KeyRelease:
  839. #if DEBUG==TRUE
  840. printf("keyrelease: %X\n",XLookupKeysym(&report.xkey, 0));
  841. #endif
  842. if (XLookupKeysym(&report.xkey, 0) == XK_Alt_R ||
  843. XLookupKeysym(&report.xkey, 0) == XK_Alt_L) {
  844. alt_pressed=FALSE;
  845. }
  846. if (XLookupKeysym(&report.xkey, 0) == XK_Control_R ||
  847. XLookupKeysym(&report.xkey, 0) == XK_Control_L) {
  848. control_pressed=FALSE;
  849. }
  850. break;
  851. default:
  852. break;
  853. }
  854. //selection cursor
  855. if(selcurr!=0xff){
  856. if(oldcurr!=0xff && oldcurr!=selcurr) {
  857. XPutImage(dis, win, gc, ximage,
  858. (oldcurr%20)*32, (oldcurr/20)*32,
  859. (oldcurr%20)*32, (oldcurr/20)*32,
  860. 33, 33);
  861. oldcurr=selcurr;
  862. }
  863. XSetForeground(dis, gc, MkColor(0,0,0));
  864. XDrawRectangle(dis, win, gc, (selcurr%20)*32, (selcurr/20)*32, 32, 32);
  865. XSetForeground(dis, gc, MkColor(255,255,255));
  866. XDrawRectangle(dis, win, gc, (selcurr%20)*32+1, (selcurr/20)*32+1, 30, 30);
  867. XFlush(dis);
  868. }
  869. }
  870. //moving to the next block
  871. if(moving && movepix<=0){
  872. if(moving==1){
  873. if(move%20>0 && levelmap.map[move-1]==0xff) {
  874. if(curr==move) curr--;
  875. if(drag==move) drag--;
  876. move--; movepix=32;
  877. } else moving=0;
  878. }
  879. if(moving==2){
  880. if(move%20<19 && levelmap.map[move+1]==0xff) {
  881. if(curr==move) curr++;
  882. if(drag==move) drag++;
  883. move++; movepix=32;
  884. } else moving=0;
  885. }
  886. if(moving==3){
  887. if(move>=20 && levelmap.map[move-20]==0xff) {
  888. if(curr==move) curr-=20;
  889. if(drag==move) drag-=20;
  890. move-=20; movepix=32;
  891. } else moving=0;
  892. }
  893. if(moving==4){
  894. if(move<=200 && levelmap.map[move+20]==0xff) {
  895. if(curr==move) curr+=20;
  896. if(drag==move) drag+=20;
  897. move+=20; movepix=32;
  898. } else moving=0;
  899. }
  900. if(moving==0){
  901. movepix=0; levelmap.map[move]=mtile;
  902. CopyImage(0,ximage,
  903. (move%20)*32, (move/20)*32,
  904. tiles,
  905. (mtile/3)*32, (mtile%3)*32+levelmap.tileset*96,
  906. 32, 32);
  907. exposehandler();
  908. }
  909. }
  910. if(moving){
  911. if(moving==1) {
  912. mx=(move%20)*32+movepix; my=(move/20)*32;
  913. }
  914. if(moving==2) {
  915. mx=(move%20)*32-movepix; my=(move/20)*32;
  916. }
  917. if(moving==3) {
  918. mx=(move%20)*32; my=(move/20)*32+movepix;
  919. }
  920. if(moving==4) {
  921. mx=(move%20)*32; my=(move/20)*32-movepix;
  922. }
  923. CopyImage(0,ximage, mx, my, tiles, (mtile/3)*32, (mtile%3)*32+levelmap.tileset*96,32, 32);
  924. if(drag==move) CopyImage(1,ximage, mx, my, dragon, 0, (moving%4)*32, 32, 32);
  925. exposehandler();
  926. CopyImage(0,ximage, mx, my, bgr, levelmap.tileset*640+mx, levelmap.background*352+my, 32, 32);
  927. movepix-=11;
  928. }
  929. if(traveling){
  930. if(levelmap.map[olddrag]==23) levelmap.map[olddrag]=0xff;
  931. if(levelmap.map[olddrag]==20) levelmap.map[olddrag]+=3;
  932. if(levelmap.map[olddrag]==17) levelmap.map[olddrag]+=3;
  933. if(levelmap.map[olddrag]==14) levelmap.map[olddrag]+=3;
  934. if(levelmap.map[olddrag]==11) levelmap.map[olddrag]+=3;
  935. if(levelmap.map[drag]==21) {timecnt+=100*(lightgame+1); levelmap.map[drag]=10;}
  936. if(levelmap.map[drag]==15)
  937. if(greenkey>0) {
  938. greenkey--; levelmap.map[drag]=10;
  939. } else {
  940. traveling=0; movepix=0; drag=olddrag;
  941. }
  942. if(levelmap.map[drag]==16) { greenkey++; levelmap.map[drag]=10; }
  943. if(levelmap.map[drag]==18)
  944. if(redkey>0) {
  945. redkey--; levelmap.map[drag]=10;
  946. } else {
  947. traveling=0; movepix=0; drag=olddrag;
  948. }
  949. if(levelmap.map[drag]==19) { redkey++; levelmap.map[drag]=10; }
  950. if(traveling==1) {
  951. mx=(drag%20)*32+movepix; my=(drag/20)*32;
  952. }
  953. if(traveling==2) {
  954. mx=(drag%20)*32-movepix; my=(drag/20)*32;
  955. }
  956. if(traveling==3) {
  957. mx=(drag%20)*32; my=(drag/20)*32+movepix;
  958. }
  959. if(traveling==4) {
  960. mx=(drag%20)*32; my=(drag/20)*32-movepix;
  961. }
  962. CopyImage(0,ximage,
  963. (drag%20)*32, (drag/20)*32,
  964. tiles,
  965. (levelmap.map[drag]/3)*32, (levelmap.map[drag]%3)*32+levelmap.tileset*96,
  966. 32, 32);
  967. CopyImage(0, ximage,
  968. (olddrag%20)*32, (olddrag/20)*32,
  969. bgr,
  970. levelmap.tileset*640+(olddrag%20)*32, levelmap.background*352+(olddrag/20)*32,
  971. 32, 32);
  972. if(levelmap.map[olddrag]!=0xff)
  973. CopyImage(1,ximage,
  974. (olddrag%20)*32, (olddrag/20)*32,
  975. tiles,
  976. (levelmap.map[olddrag]/3)*32, (levelmap.map[olddrag]%3)*32+levelmap.tileset*96,
  977. 32, 32);
  978. CopyImage(1,ximage, mx, my, dragon, (32-movepix)*4, (traveling%4)*32, 32, 32);
  979. exposehandler();
  980. movepix-=8;
  981. }
  982. if(traveling && movepix<0) {
  983. traveling=0; movepix=0;
  984. CopyImage(0,ximage,
  985. (drag%20)*32, (drag/20)*32,
  986. tiles,
  987. (levelmap.map[drag]/3)*32, (levelmap.map[drag]%3)*32+levelmap.tileset*96,
  988. 32, 32);
  989. CopyImage(1,ximage, (drag%20)*32, (drag/20)*32, dragon, 0, 0, 32, 32);
  990. if(levelmap.map[drag]==22) {
  991. olddrag=drag;
  992. drag++; if(drag>220) drag=0;
  993. while(levelmap.map[drag]!=22) {drag++; if(drag>220) drag=0; }
  994. transporting=1; movepix=7;
  995. }
  996. if(levelmap.map[drag]==12) if(!leaving){
  997. leaving=1; movepix=4;
  998. }
  999. }
  1000. //moving or travelling on a stone
  1001. if(transporting){
  1002. if(movepix>3){
  1003. //disapear
  1004. CopyImage(0,ximage,
  1005. (olddrag%20)*32, (olddrag/20)*32,
  1006. tiles,
  1007. (levelmap.map[olddrag]/3)*32, (levelmap.map[olddrag]%3)*32+levelmap.tileset*96,
  1008. 32, 32);
  1009. CopyImage(1, ximage, (olddrag%20)*32, (olddrag/20)*32, dragon, (7-movepix)*32, 128, 32, 32);
  1010. } else {
  1011. //apear
  1012. if(movepix==3)
  1013. CopyImage(0,ximage,
  1014. (olddrag%20)*32, (olddrag/20)*32,
  1015. tiles,
  1016. (levelmap.map[olddrag]/3)*32, (levelmap.map[olddrag]%3)*32+levelmap.tileset*96,
  1017. 32, 32);
  1018. CopyImage(1, ximage, (drag%20)*32, (drag/20)*32, dragon, movepix*32, 128, 32, 32);
  1019. }
  1020. exposehandler();
  1021. movepix--;
  1022. if(movepix<0){ transporting=0; exposehandler();}
  1023. }
  1024. //entering the scene
  1025. if(entering){
  1026. for(i=0;i<220;i++) if(levelmap.map[i]==12 || levelmap.map[i]==13){
  1027. CopyImage(0, ximage,
  1028. (i%20)*32, (i/20)*32,
  1029. tiles,
  1030. (levelmap.map[i]/3)*32, (levelmap.map[i]%3)*32+levelmap.tileset*96,
  1031. 32, 32);
  1032. }
  1033. if(movepix>=0){
  1034. if(movepix<5) CopyImage(1, ximage, (drag%20)*32, (drag/20)*32, dragon, (4-movepix)*32, 160, 32, 32);
  1035. for(i=0;i<220;i++) if(levelmap.map[i]==12){
  1036. CopyImage(0, ximage,
  1037. (i%20)*32, (i/20)*32,
  1038. tiles,
  1039. (levelmap.map[i]/3)*32, (levelmap.map[i]%3)*32+levelmap.tileset*96,
  1040. 32, 32);
  1041. CopyImage(1, ximage,
  1042. (i%20)*32, (i/20)*32,
  1043. dragon,
  1044. (4-(movepix%4))*32, 224,
  1045. 32, 32);
  1046. }
  1047. }
  1048. exposehandler();
  1049. movepix--;
  1050. if(movepix<0){
  1051. entering=0;
  1052. for(i=0;i<220;i++)
  1053. if(levelmap.map[i]==12 || levelmap.map[i]==13){
  1054. CopyImage(0, ximage,
  1055. (i%20)*32, (i/20)*32,
  1056. tiles,
  1057. (levelmap.map[i]/3)*32, (levelmap.map[i]%3)*32+levelmap.tileset*96,
  1058. 32, 32);
  1059. }
  1060. timecnt=levelmap.soltime*(lightgame+1);
  1061. oldt=newt=time(NULL);
  1062. exposehandler();
  1063. }
  1064. }
  1065. //leaving the scene
  1066. if(leaving){
  1067. CopyImage(0, ximage,
  1068. (drag%20)*32, (drag/20)*32,
  1069. tiles,
  1070. (levelmap.map[drag]/3)*32, (levelmap.map[drag]%3)*32+levelmap.tileset*96,
  1071. 32, 32);
  1072. if(movepix>0)
  1073. CopyImage(1, ximage, (drag%20)*32, (drag/20)*32, dragon, (4-movepix)*32, 192, 32, 32);
  1074. exposehandler();
  1075. movepix--;
  1076. if(movepix<0){ leaving=0; exitgame=3; }
  1077. }
  1078. }
  1079. fadeimage(3,0,0,ximage);
  1080. temp=CreateEmptyImage();
  1081. //empty keyboard buffer
  1082. while(XPending(dis)) XNextEvent(dis, &report);
  1083. //run out of time
  1084. if(exitgame==1){
  1085. sprintf(duma,"\n<A STRONG BLOW AND>\n"
  1086. "ALL AROUND YOU FADES<TO BLACK. LUCKY AS>"
  1087. "_EVER, YOU FIND YOUR<WAY BACK TO WHERE>\n"
  1088. "__<YOU STARTED !>\n\n"
  1089. "_<NOW, YOU HAVE %d>\n"
  1090. "__<CANDLES LEFT.>",candles);
  1091. drawtext(temp,0,0,(char*)duma);
  1092. subtitle(0,0,temp,ximage);
  1093. for(i=0;i<numlevels;i++){
  1094. if(strncmp(levelmap.code,levels[i].code,6)==0){
  1095. memcpy(&levelmap,&levels[i],sizeof(level));
  1096. i=numlevels;
  1097. }
  1098. }
  1099. }
  1100. //game over
  1101. if(exitgame==2){
  1102. drawtext(temp,0,0,"\n\n\n\n<SORRY, MY FRIEND,>\n"
  1103. "<THERE ARE NO MORE>\n"
  1104. "_<CANDLES IN YOUR>\n"
  1105. "____<POCKET !!!>");
  1106. subtitle(0,0,temp,ximage);
  1107. }
  1108. //level completed
  1109. if(exitgame==3){
  1110. //succeded :-)
  1111. oldscore=score;
  1112. if(lightgame) score+=(worth/2+timecnt/4+candles); else score+=(worth+timecnt+candles);
  1113. if(score>999999) score=999999;
  1114. if(lightgame) {i=10; j=5000;} else {i=5; j=10000;}
  1115. if(candles<i && oldscore/j!=score/j) candles++;
  1116. sprintf(duma,"\n<YOUR SCORE:%6d>\n___<CANDLES: %d>\n\n",score,candles);
  1117. if(strcmp(levelmap.nextlink,"ENDSEQ")!=0){
  1118. if(score%3==0)
  1119. strcat(duma,"THINKING OF NOTHING\n"
  1120. "<SPECIAL, SUDDENLY>\n"
  1121. "YOUR ONLY THOUGHT IS<"
  1122. "THAT SINGLE WORD:>\n");
  1123. if(score%3==1)
  1124. strcat(duma,"AS YOU STEP THRU THE"
  1125. "EXIT, YOU FIND SOME>"
  1126. "LETTERS SCRIBBLED ON"
  1127. "THE FLOOR. THESE ARE:");
  1128. if(score%3==2)
  1129. strcat(duma,"GLANCING AT THE WALL"
  1130. "YOU REALIZE A DARK,>"
  1131. "<STRANGE WRITING !>\n"
  1132. "WHAT COULD IT MEAN?\n");
  1133. strcat(duma,"\n______<");
  1134. strcat(duma,levelmap.nextlink);
  1135. strcat(duma,">");
  1136. drawtext(temp,0,0,(char*)duma);
  1137. subtitle(0,0,temp,ximage);
  1138. }
  1139. }
  1140. DestroyImage(temp);
  1141. }
  1142. //stop background music
  1143. if(musicpid!=0) {
  1144. kill(musicpid,-9);
  1145. system("killall -9 mpg123 2>/dev/null >/dev/null");
  1146. musicpid=0;
  1147. }
  1148. //add user to hi scores
  1149. for(i=0;i<9;i++){
  1150. if(hiscores[i].score<score){
  1151. for(j=8;j>i;j--){
  1152. memcpy(&hiscores[j],&hiscores[j-1],sizeof(hscoretype));
  1153. }
  1154. hiscores[i].score=score;
  1155. strncpy(hiscores[i].name,getenv("LOGNAME"),12);
  1156. j=0;
  1157. while(hiscores[i].name[j]!=0 && j<12){
  1158. c=hiscores[i].name[j];
  1159. if(c>='a' && c<='z') c-=32;
  1160. if(c<'0') c=' ';
  1161. if(c>9 && c<'A') c=' ';
  1162. if(c>'Z') c=' ';
  1163. hiscores[i].name[j]=c;
  1164. j++;
  1165. }
  1166. savescorefile();
  1167. loadscorefile();
  1168. displayhiscore();
  1169. i=9;
  1170. }
  1171. }
  1172. }
  1173. //main function nothing important :-)
  1174. int main(int argc, char* argv[])
  1175. {
  1176. gzFile gf;
  1177. int f;
  1178. char c;
  1179. umask(10);
  1180. printf("xStoneAge for Linux\nVersion: 1.0\nWritten by bzt 2003\n");
  1181. scorefile[0]=0;
  1182. loadscorefile();
  1183. //load files
  1184. gf=gzopen("/usr/lib/xstoneage/stoneage.pak","r");
  1185. if(gf==NULL){
  1186. gf=gzopen("./stoneage.pak","r");
  1187. if(gf==NULL){
  1188. fprintf(stderr,"Could not found data file (/usr/lib/xstoneage/stoneage.pak)\n");
  1189. exit(1);
  1190. }
  1191. }
  1192. initdisplay("xStoneAge",640,400);
  1193. if(!(tiles=loadtga(gf))) exit(1);
  1194. if(!(sidebars=loadtga(gf))) exit(1);
  1195. if(!(bgr=loadtga(gf))) exit(1);
  1196. if(!(eyes=loadtga(gf))) exit(1);
  1197. if(!(stoneage=loadtga(gf))) exit(1);
  1198. if(!(menu=loadtga(gf))) exit(1);
  1199. if(!(light=loadtga(gf))) exit(1);
  1200. if(!(pass=loadtga(gf))) exit(1);
  1201. if(!(hiscore=loadtga(gf))) exit(1);
  1202. if(!(endseq=loadtga(gf))) exit(1);
  1203. if(!(fonts=loadtga(gf))) exit(1);
  1204. if(!(fonts2=loadtga(gf))) exit(1);
  1205. if(!(dragon=loadtga(gf))) exit(1);
  1206. if(!(pauseimg=loadtga(gf))) exit(1);
  1207. //read level maps
  1208. numlevels=0;
  1209. while(gzread(gf,&levels[numlevels],sizeof(level))>0) numlevels++;
  1210. //end load files
  1211. gzclose(gf);
  1212. #if DEBUG==TRUE
  1213. printf("Files loaded.\n");
  1214. #endif
  1215. //intro
  1216. ximage=CreateEmptyImage();
  1217. fadeimage(FADEINOUT,0,0,stoneage); XFlush(dis);
  1218. CopyImage(0, ximage, 0, 0, menu, 0, 0, menu->width, menu->height);
  1219. fadeimage(FADEIN,0,0,ximage); XFlush(dis);
  1220. #if DEBUG==TRUE
  1221. printf("Main menu loop comes.\n");
  1222. #endif
  1223. mode=0; lightgame=0;
  1224. //menu comes here
  1225. while (1) {
  1226. report.type=None;
  1227. //get an event, block until we have one
  1228. XNextEvent(dis, &report);
  1229. switch (report.type) {
  1230. case ButtonPress:
  1231. #if DEBUG==TRUE
  1232. printf("Mouse button pressed at %d %d.\n",report.xbutton.x,report.xbutton.y);
  1233. #endif
  1234. mousebutton_pressed=TRUE;
  1235. mousex=report.xbutton.x;
  1236. mousey=report.xbutton.y;
  1237. break;
  1238. case ButtonRelease:
  1239. #if DEBUG==TRUE
  1240. printf("Mouse button released at %d %d mode %d.\n",report.xbutton.x,report.xbutton.y,mode);
  1241. #endif
  1242. mousebutton_pressed=FALSE;
  1243. //main menu
  1244. if(mode==0){
  1245. if (mousex>=160 && mousey>=150 && mousex<=470 && mousey<=170) startgame();
  1246. if (mousex>=160 && mousey>=175 && mousex<=470 && mousey<=195) getcode();
  1247. if (mousex>=160 && mousey>=200 && mousex<=470 && mousey<=220) doscores();
  1248. if (mousex>=160 && mousey>=225 && mousex<=470 && mousey<=245) dodifficulty();
  1249. if (mousex>=160 && mousey>=250 && mousex<=470 && mousey<=270) doeditor();
  1250. }
  1251. //options
  1252. if(mode==1){
  1253. if (mousex>=190 && mousey>=240 && mousex<=300 && mousey<=260) {
  1254. //cancel
  1255. //fadeimage(FADEOUT,160,125,options);
  1256. //fadeimage(FADEIN,160,125,menu);
  1257. //CopyImage(0, ximage, 160, 125, menu, 0, 0, menu->width, menu->height);
  1258. mode=0;
  1259. }
  1260. if (mousex>=370 && mousey>=240 && mousex<=440 && mousey<=260) {
  1261. //ok
  1262. //fadeimage(FADEOUT,160,125,options);
  1263. //fadeimage(FADEIN,160,125,menu);
  1264. //CopyImage(0, ximage, 160, 125, menu, 0, 0, menu->width, menu->height);
  1265. mode=0;
  1266. }
  1267. }
  1268. break;
  1269. case ResizeRequest:
  1270. #if DEBUG==TRUE
  1271. printf("I have been resized.\n");
  1272. #endif
  1273. XSetForeground(dis, gc, BlackPixel(dis,0)); XClearWindow(dis,win);
  1274. break;
  1275. case Expose:
  1276. #if DEBUG==TRUE
  1277. printf("I have been exposed.\n");
  1278. #endif
  1279. XPutImage(dis, win, gc, ximage,
  1280. report.xexpose.x,report.xexpose.y,
  1281. report.xexpose.x,report.xexpose.y,
  1282. report.xexpose.width, report.xexpose.height);
  1283. XSync(dis,FALSE);
  1284. break;
  1285. case KeyPress:
  1286. #if DEBUG==TRUE
  1287. printf("keypress: %d %X\n",mode,XLookupKeysym(&report.xkey, 0));
  1288. #endif
  1289. /*Close the program if Escape or ALT+F4 is pressed.*/
  1290. if (XLookupKeysym(&report.xkey, 0) == XK_Escape ||
  1291. (XLookupKeysym(&report.xkey, 0) == XK_F4 && alt_pressed==TRUE)) {
  1292. if(mode==0) byez();
  1293. if(mode==1){
  1294. mode=0;
  1295. }
  1296. if(mode==2){
  1297. fadeimage(FADEOUT,0,0,ximage);
  1298. CopyImage(0, ximage, 0, 0, menu, 0, 0, menu->width, menu->height);
  1299. fadeimage(FADEIN,0,0,ximage);
  1300. mode=0;
  1301. }
  1302. }
  1303. if (XLookupKeysym(&report.xkey, 0) == XK_Alt_R ||
  1304. XLookupKeysym(&report.xkey, 0) == XK_Alt_L) {
  1305. alt_pressed=TRUE;
  1306. }
  1307. //query level code
  1308. if(mode==2){
  1309. f=1; c=0;
  1310. //entered 6 chars
  1311. if(XLookupKeysym(&report.xkey,0) == XK_Return && codeptr==6) {
  1312. fadeimage(FADEOUT,0,0,ximage); mode=0;
  1313. score=0; candles=lightgame?10:5;
  1314. dothegame();
  1315. CopyImage(0, ximage, 0, 0, menu, 0, 0, menu->width, menu->height);
  1316. fadeimage(FADEIN,0,0,ximage);
  1317. f=0;
  1318. }
  1319. if(XLookupKeysym(&report.xkey,0) == XK_BackSpace)
  1320. if(codeptr<=0) {
  1321. codeptr=0;
  1322. } else {
  1323. codeptr--; levelmap.nextlink[codeptr]=0; f=0;
  1324. }
  1325. if(XLookupKeysym(&report.xkey,0) == XK_a) if(codeptr<6){ c='A'; f=0;}
  1326. if(XLookupKeysym(&report.xkey,0) == XK_b) if(codeptr<6){ c='B'; f=0;}
  1327. if(XLookupKeysym(&report.xkey,0) == XK_c) if(codeptr<6){ c='C'; f=0;}
  1328. if(XLookupKeysym(&report.xkey,0) == XK_d) if(codeptr<6){ c='D'; f=0;}
  1329. if(XLookupKeysym(&report.xkey,0) == XK_e) if(codeptr<6){ c='E'; f=0;}
  1330. if(XLookupKeysym(&report.xkey,0) == XK_f) if(codeptr<6){ c='F'; f=0;}
  1331. if(XLookupKeysym(&report.xkey,0) == XK_g) if(codeptr<6){ c='G'; f=0;}
  1332. if(XLookupKeysym(&report.xkey,0) == XK_h) if(codeptr<6){ c='H'; f=0;}
  1333. if(XLookupKeysym(&report.xkey,0) == XK_i) if(codeptr<6){ c='I'; f=0;}
  1334. if(XLookupKeysym(&report.xkey,0) == XK_j) if(codeptr<6){ c='J'; f=0;}
  1335. if(XLookupKeysym(&report.xkey,0) == XK_k) if(codeptr<6){ c='K'; f=0;}
  1336. if(XLookupKeysym(&report.xkey,0) == XK_l) if(codeptr<6){ c='L'; f=0;}
  1337. if(XLookupKeysym(&report.xkey,0) == XK_m) if(codeptr<6){ c='M'; f=0;}
  1338. if(XLookupKeysym(&report.xkey,0) == XK_n) if(codeptr<6){ c='N'; f=0;}
  1339. if(XLookupKeysym(&report.xkey,0) == XK_o) if(codeptr<6){ c='O'; f=0;}
  1340. if(XLookupKeysym(&report.xkey,0) == XK_p) if(codeptr<6){ c='P'; f=0;}
  1341. if(XLookupKeysym(&report.xkey,0) == XK_q) if(codeptr<6){ c='Q'; f=0;}
  1342. if(XLookupKeysym(&report.xkey,0) == XK_r) if(codeptr<6){ c='R'; f=0;}
  1343. if(XLookupKeysym(&report.xkey,0) == XK_s) if(codeptr<6){ c='S'; f=0;}
  1344. if(XLookupKeysym(&report.xkey,0) == XK_t) if(codeptr<6){ c='T'; f=0;}
  1345. if(XLookupKeysym(&report.xkey,0) == XK_u) if(codeptr<6){ c='U'; f=0;}
  1346. if(XLookupKeysym(&report.xkey,0) == XK_v) if(codeptr<6){ c='V'; f=0;}
  1347. if(XLookupKeysym(&report.xkey,0) == XK_w) if(codeptr<6){ c='W'; f=0;}
  1348. if(XLookupKeysym(&report.xkey,0) == XK_x) if(codeptr<6){ c='X'; f=0;}
  1349. if(XLookupKeysym(&report.xkey,0) == XK_y) if(codeptr<6){ c='Y'; f=0;}
  1350. if(XLookupKeysym(&report.xkey,0) == XK_z) if(codeptr<6){ c='Z'; f=0;}
  1351. if(f){
  1352. printf("\007"); fflush(stdout);
  1353. }
  1354. if(c){
  1355. levelmap.nextlink[codeptr]=c;
  1356. levelmap.nextlink[codeptr+1]=0;
  1357. c-='A';
  1358. CopyImage(0, ximage, 265+codeptr*35, 168, fonts, c*32, 0, 32, 32);
  1359. codeptr++;
  1360. }
  1361. CopyImage(0, ximage, 265+codeptr*35, 168, pass, 265+codeptr*35, 168, 230-codeptr*35, 32);
  1362. XPutImage(dis, win, gc, ximage, 265, 168, 265, 168, 35*6, 32);
  1363. XSync(dis,FALSE);
  1364. }
  1365. //main menu
  1366. if(mode==0){
  1367. if (XLookupKeysym(&report.xkey, 0) == XK_F1) startgame();
  1368. if (XLookupKeysym(&report.xkey, 0) == XK_F2) getcode();
  1369. if (XLookupKeysym(&report.xkey, 0) == XK_F3) doscores();
  1370. if (XLookupKeysym(&report.xkey, 0) == XK_F4) dodifficulty();
  1371. if (XLookupKeysym(&report.xkey, 0) == XK_F5) doeditor();
  1372. }
  1373. break;
  1374. case KeyRelease:
  1375. #if DEBUG==TRUE
  1376. printf("keyrelease: %X\n",XLookupKeysym(&report.xkey, 0));
  1377. #endif
  1378. if (XLookupKeysym(&report.xkey, 0) == XK_Alt_R ||
  1379. XLookupKeysym(&report.xkey, 0) == XK_Alt_L) {
  1380. alt_pressed=FALSE;
  1381. }
  1382. break;
  1383. default:
  1384. break;
  1385. }//event switch
  1386. }
  1387. // menu end, this code should be never reached
  1388. return(0);
  1389. }