OSDN Git Service

wwww
[proj16/16.git] / 16 / v2 / source / verge / MAPED / COLUMNS.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 #include "maped.h"\r
18 \r
19 #include <stdio.h>\r
20 #include <string.h>\r
21 #include <malloc.h>\r
22 #include <stdlib.h>\r
23 #include <time.h>\r
24 \r
25 #include "config.h"\r
26 #include "keyboard.h"\r
27 #include "timer.h"\r
28 #include "vdriver.h"\r
29 \r
30 #include "colbak.h"\r
31 #include "colstuff.h"\r
32 \r
33 #include "smalfont.h"\r
34 #include "gui.h"\r
35 \r
36 #include "tilesel.h"\r
37 \r
38 #define byte unsigned char\r
39 #define word unsigned short\r
40 \r
41 // ================================= Data ====================================\r
42 \r
43 char *field, *destruct;\r
44 char *background, *sprites;\r
45 int startofs=16;\r
46 int turnlength, turnctr;\r
47 int destructed, difficulty=4;\r
48 int blocks, score, scoremultiplier;\r
49 int level;\r
50 \r
51 // Current piece falling\r
52 \r
53 char piece[3], tempspot;\r
54 int xpos, ypos, ypofs;\r
55 char newpiece;\r
56 char nextpiece[3];\r
57 \r
58 // ================================= Code ====================================\r
59 \r
60 void BlitPlayField()\r
61 {\r
62   int i, j;\r
63   char c;\r
64 \r
65   for (i=0; i<12; i++)\r
66     for (j=0; j<6; j++)\r
67     {\r
68       c=field[(i*6)+j];\r
69       if (c) TCopySprite(128+(j*16), startofs+4+(i*16), 16, 16, sprites+((c+1)*256));\r
70     }\r
71 }\r
72 \r
73 void BlitPlayFieldwDestruct(char flash)\r
74 {\r
75   int i, j;\r
76   char c;\r
77 \r
78   for (i=0; i<12; i++)\r
79     for (j=0; j<6; j++)\r
80     {\r
81       c=field[(i*6)+j];\r
82       if (c && !destruct[(i*6)+j])\r
83         TCopySprite(128+(j*16), startofs+4+(i*16), 16, 16, sprites+((c+1)*256));\r
84       if (destruct[(i*6)+j])\r
85         TCopySprite(128+(j*16), startofs+4+(i*16), 16, 16, sprites+(flash*256));\r
86     }\r
87 }\r
88 \r
89 void BlitPiece()\r
90 {\r
91   ypofs=((100 * turnctr) / turnlength) * 16 / 100;\r
92 \r
93   TCopySprite(128+(xpos*16), startofs+4+(ypos*16)+ypofs, 16, 16, sprites+((piece[0]+1)*256));\r
94   TCopySprite(128+(xpos*16), startofs+20+(ypos*16)+ypofs, 16, 16, sprites+((piece[1]+1)*256));\r
95   TCopySprite(128+(xpos*16), startofs+36+(ypos*16)+ypofs, 16, 16, sprites+((piece[2]+1)*256));\r
96 \r
97   TCopySprite(276, startofs+70, 16, 16, sprites+((nextpiece[0]+1)*256));\r
98   TCopySprite(276, startofs+90, 16, 16, sprites+((nextpiece[1]+1)*256));\r
99   TCopySprite(276, startofs+110, 16, 16, sprites+((nextpiece[2]+1)*256));\r
100 }\r
101 \r
102 void GenerateNewPiece()\r
103 {\r
104   newpiece=0;\r
105   xpos=2;\r
106   ypos=0;\r
107   if (field[2])  key[SCAN_ESC]=1;\r
108   if (field[8])  key[SCAN_ESC]=1;\r
109   if (field[14]) key[SCAN_ESC]=1;\r
110   if (field[20]) key[SCAN_ESC]=1;\r
111 \r
112   if (key[SCAN_ESC])\r
113   {\r
114     if (difficulty==4 && blocks<240) Message("You really suck at columns, man.",300);\r
115     if (difficulty==5 && blocks<80)  Message("You really suck at columns, man.",300);\r
116     if (score>3200 && score<=6400) Message("Not bad.",300);\r
117     if (score>6400) Message("Behold, the Columns God walks among us.",500);\r
118   }\r
119 \r
120   memcpy(&piece, &nextpiece, 3);\r
121   nextpiece[0]=random(1,difficulty);\r
122   nextpiece[1]=random(1,difficulty);\r
123   nextpiece[2]=random(1,difficulty);\r
124 }\r
125 \r
126 void DestroyBlock(int x, int y)\r
127 {\r
128   int i;\r
129 \r
130   for (i=y; i>0; i--)\r
131   {\r
132     field[(i*6)+x]=field[((i-1)*6)+x];\r
133   }\r
134   blocks++;\r
135   score+=scoremultiplier;\r
136 }\r
137 \r
138 void ClearConsecutiveColumns()\r
139 {\r
140   int x, y;\r
141   char c;\r
142 \r
143   // Scan for things to destroy, but don't destroy them, just mark\r
144   // them in the Destroy field.\r
145 \r
146   destructed=0;\r
147   memset(destruct, 0, (6*13));\r
148 \r
149   for (y=0; y<12; y++)\r
150     for (x=0; x<6; x++)\r
151     {\r
152       c=field[(y*6)+x];\r
153 \r
154       // Test vertical match\r
155       if (y<10)\r
156       {\r
157         if ((field[((y+1)*6)+x]==c) && (field[((y+2)*6)+x]==c) && c)\r
158         {\r
159           // vertical match. Set destruct field.\r
160           destruct[((y+0)*6)+x]=1;\r
161           destruct[((y+1)*6)+x]=1;\r
162           destruct[((y+2)*6)+x]=1;\r
163           destructed=1;\r
164         }\r
165       }\r
166       // Test horizontal match\r
167       if (x<4)\r
168       {\r
169         if ((field[(y*6)+x+1]==c) && (field[(y*6)+x+2]==c) && c)\r
170         {\r
171           // horizontal match. Set destruct field.\r
172           destruct[(y*6)+x+0]=1;\r
173           destruct[(y*6)+x+1]=1;\r
174           destruct[(y*6)+x+2]=1;\r
175           destructed=1;\r
176         }\r
177       }\r
178       // Test negative diagonal match\r
179       if (x<4 && y<10)\r
180       {\r
181          if ((field[((y+1)*6)+x+1]==c) && (field[((y+2)*6)+x+2]==c) && c)\r
182          {\r
183            // negative diagonal match. set destruct field.\r
184            destruct[((y+0)*6)+x+0]=1;\r
185            destruct[((y+1)*6)+x+1]=1;\r
186            destruct[((y+2)*6)+x+2]=1;\r
187            destructed=1;\r
188          }\r
189       }\r
190       // Test positive diagonal match\r
191       if (x>=2 && y<10)\r
192       {\r
193          if ((field[((y+1)*6)+x-1]==c) && (field[((y+2)*6)+x-2]==c) && c)\r
194          {\r
195            // positive diagonal match. set destruct field.\r
196            destruct[((y+0)*6)+x-0]=1;\r
197            destruct[((y+1)*6)+x-1]=1;\r
198            destruct[((y+2)*6)+x-2]=1;\r
199            destructed=1;\r
200          }\r
201       }\r
202     }\r
203 \r
204   // Show which tiles are being destroyed before clearing out for increase\r
205   // visual coolishness.\r
206 \r
207   if (destructed)\r
208   {\r
209     timer_count=0;\r
210     while (timer_count<50)\r
211     {\r
212       if (timer_count<10 || (timer_count>20 && timer_count<30) ||\r
213          (timer_count>40 && timer_count<50)) c=1;\r
214       else c=0;\r
215 \r
216       CopySprite(16,16,320,200,background);\r
217       BlitPlayFieldwDestruct(c);\r
218       TCopySprite(276, startofs+70, 16, 16, sprites+((nextpiece[0]+1)*256));\r
219       TCopySprite(276, startofs+90, 16, 16, sprites+((nextpiece[1]+1)*256));\r
220       TCopySprite(276, startofs+110, 16, 16, sprites+((nextpiece[2]+1)*256));\r
221 \r
222 GotoXY(55,130);\r
223 sprintf(strbuf,"Blocks: %d", blocks);\r
224 printstring(strbuf);\r
225 GotoXY(55,140);\r
226 sprintf(strbuf,"Score: %d", score);\r
227 printstring(strbuf);\r
228 GotoXY(55,150);\r
229 sprintf(strbuf,"Level: %d", level);\r
230 printstring(strbuf);\r
231 \r
232       ShowPage();\r
233     }\r
234   }\r
235 \r
236   // Apply destruct-o patch to the field.\r
237 \r
238   for (y=0; y<12; y++)\r
239     for (x=0; x<6; x++)\r
240       if (destruct[(y*6)+x]) DestroyBlock(x,y);\r
241 }\r
242 \r
243 void NextTurn()\r
244 {\r
245   ypos++;\r
246   if (field[((ypos+3)*6)+xpos])\r
247   {\r
248     if (ypos<3) key[SCAN_ESC]=1;\r
249     // Hit something; set piece here.\r
250     field[(ypos*6)+xpos]=piece[0];\r
251     field[((ypos+1)*6)+xpos]=piece[1];\r
252     field[((ypos+2)*6)+xpos]=piece[2];\r
253     newpiece=1;\r
254 \r
255     // Scan for consecutive things to delete.\r
256     do\r
257     {\r
258       ClearConsecutiveColumns();\r
259       scoremultiplier*=2;\r
260     } while (destructed);\r
261   }\r
262 }\r
263 \r
264 int CanGoLeft()\r
265 {\r
266   if (!xpos) return 0;\r
267   if (field[((ypos+1)*6)+xpos-1]) return 0;\r
268   if (field[((ypos+2)*6)+xpos-1]) return 0;\r
269   if (field[((ypos+3)*6)+xpos-1]) return 0;\r
270   return 1;\r
271 }\r
272 \r
273 int CanGoRight()\r
274 {\r
275   if (xpos==5) return 0;\r
276   if (field[((ypos+1)*6)+xpos+1]) return 0;\r
277   if (field[((ypos+2)*6)+xpos+1]) return 0;\r
278   if (field[((ypos+3)*6)+xpos+1]) return 0;\r
279   return 1;\r
280 }\r
281 \r
282 void RotatePiece()\r
283 {\r
284   tempspot=piece[0];\r
285   piece[0]=piece[1];\r
286   piece[1]=piece[2];\r
287   piece[2]=tempspot;\r
288 }\r
289 \r
290 void ProcessLevels()\r
291 {\r
292   if (blocks>80)  { level=2; turnlength=90; }\r
293   if (blocks>160) { level=3; turnlength=80; }\r
294   if (blocks>240) { level=4; turnlength=70; }\r
295   if (blocks>320) { level=5; turnlength=60; }\r
296   if (blocks>400) { level=6; turnlength=50; }\r
297   if (blocks>480) { level=7; turnlength=40; }\r
298   if (blocks>560) { level=8; turnlength=30; }\r
299   if (blocks>640) { level=9; turnlength=20; }\r
300 }\r
301 \r
302 extern FILE *pcxf;\r
303 extern int width, depth;\r
304 extern int bytes;\r
305 extern int vidoffset;\r
306 \r
307 void LoadBackground()\r
308 {\r
309   int i;\r
310 \r
311   if (!(pcxf=fopen("colback.pcx","rb")))\r
312   {\r
313     background=background_;\r
314   }\r
315   else\r
316   {\r
317     fclose(pcxf);\r
318     background=(char *) valloc(64000,"col bakg",0);\r
319     LoadPCXHeaderNP("colback.pcx");\r
320     for (i=0; i<depth; i++)\r
321     {\r
322        vidoffset=width*i;\r
323        ReadPCXLine(background);\r
324     }\r
325     fclose(pcxf);\r
326   }\r
327 \r
328   if (!(pcxf=fopen("colspr.pcx","rb")))\r
329   {\r
330     sprites=sprites_;\r
331   }\r
332   else\r
333   {\r
334     fclose(pcxf);\r
335     LoadPCXHeaderNP("colspr.pcx");\r
336     sprites=(char *) valloc(width*depth,"col spr",0);\r
337     for (i=0; i<depth; i++)\r
338     {\r
339        vidoffset=width*i;\r
340        ReadPCXLine(sprites);\r
341     }\r
342     fclose(pcxf);\r
343   }\r
344 }\r
345 \r
346 void Columns()\r
347 {\r
348   ClearScreen();\r
349   srand(time(NULL));\r
350   LoadBackground();\r
351   field=(char *) valloc(6*13,"col field",0);\r
352   destruct=(char *) valloc(6*13,"col dest",0);\r
353   memset(field, 0, 6*12);\r
354   memset(field+(6*12), 255, 6);\r
355   newpiece=1;\r
356   turnlength=100;\r
357   turnctr=0;\r
358   timer_count=0;\r
359   blocks=0;\r
360   score=0;\r
361   level=1;\r
362   GenerateNewPiece();\r
363   GenerateNewPiece();\r
364   while (!key[SCAN_ESC])\r
365   {\r
366     CopySprite(16,16,320,200,background);\r
367     if (key[SCAN_LEFT])\r
368     {\r
369       if (xpos && CanGoLeft()) xpos--;\r
370       key[SCAN_LEFT]=0;\r
371     }\r
372     if (key[SCAN_RIGHT])\r
373     {\r
374       if (xpos<5 && CanGoRight()) xpos++;\r
375       key[SCAN_RIGHT]=0;\r
376     }\r
377     if (key[SCAN_DOWN])\r
378     {\r
379       timer_count*=5;\r
380     }\r
381     if (key[SCAN_UP])\r
382     {\r
383       RotatePiece();\r
384       key[SCAN_UP]=0;\r
385     }\r
386     ProcessLevels();\r
387     turnctr+=timer_count;\r
388     timer_count=0;\r
389     switch (difficulty)\r
390     {\r
391       case 4: scoremultiplier=5;\r
392       case 5: scoremultiplier=10;\r
393       case 6: scoremultiplier=15;\r
394     }\r
395     if (turnctr>=turnlength)\r
396     {\r
397       NextTurn();\r
398       turnctr-=turnlength;\r
399     }\r
400     if (newpiece) GenerateNewPiece();\r
401     BlitPlayField();\r
402     BlitPiece();\r
403 \r
404 GotoXY(55,130);\r
405 sprintf(strbuf,"Blocks: %d", blocks);\r
406 printstring(strbuf);\r
407 GotoXY(55,140);\r
408 sprintf(strbuf,"Score: %d", score);\r
409 printstring(strbuf);\r
410 GotoXY(55,150);\r
411 sprintf(strbuf,"Level: %d", level);\r
412 printstring(strbuf);\r
413 \r
414     ShowPage();\r
415   }\r
416   vfree(sprites);\r
417   vfree(background);\r
418   vfree(field);\r
419   vfree(destruct);\r
420 }\r