admin
base
com
developer
drivers
ds
enduser
inetcore
inetsrv
loc
mergedcomponents
multimedia
net
printscan
public
published
sdktools
shell
applets
browseinfo
browseui
comctl32
comdlg32
cpls
ddk
docs
drts
evtmon
explorer
ext
iecontrols
iexplore
inc
lcinf
lib
osshell
accesory
accessib
control
convgrp
cpls
dskquota
encrypt
ep
aboutwep
carddll
cruel
freecell
golf
idlewild
oldtp
pegged
snake
bmp
blk.c
blk.h
context.h
grafix.c
grafix.h
level.dlg
makefile
menu.inc
pref.c
pref.h
res.h
res.rc
rtns.c
rtns.h
snake
snake.c
snake.def
snake.h
snake.hpj
sound.c
sound.h
sources
strings.inc
util.c
util.h
taipei
tetris
tictac
winmine
dirs
fontfldr
games
grptoreg
inc
lmui
migrate
pifmgr
progman
regedit.nt4
regwiz
rundll32
runonce
security
shcompui
shole
snapins
taskman
themes
tools
version
winver
dirs
policies
published
samplemusic
samplemypicts
services
shdocvw
shell32
shelldrt
shlwapi
sld
themes
thunk
tools
typebin
types
wallpaper
ccshell.ini
common.inc
common.mk
dirs
dummy.txt
gnumakefile
makefile.inc
project.mk
termsrv
tools
windows
dirs
makefil0
578 lines
9.6 KiB
C
578 lines
9.6 KiB
C
/******************/
|
||
/* SNAKE ROUTINES */
|
||
/******************/
|
||
|
||
#define _WINDOWS
|
||
#include <windows.h>
|
||
#include <port1632.h>
|
||
|
||
#include "snake.h"
|
||
#include "res.h"
|
||
#include "rtns.h"
|
||
#include "grafix.h"
|
||
#include "blk.h"
|
||
#include "pref.h"
|
||
#include "sound.h"
|
||
#include "util.h"
|
||
|
||
|
||
/*** Global/Local Variables ***/
|
||
|
||
|
||
BLK mpposblk[posMax]; /* The playing grid */
|
||
|
||
|
||
POS posHead; /* current position of head */
|
||
POS posTail; /* current position of tail */
|
||
|
||
BOOL fHead; /* True if head is visible */
|
||
BOOL fTail;
|
||
|
||
BOOL fExit = fFalse;
|
||
|
||
BOOL fPlum;
|
||
POS posPlum;
|
||
INT offPlumNS;
|
||
INT offPlumEW;
|
||
|
||
INT cDelayHead; /* Delay before head shows up */
|
||
INT cDelayTail;
|
||
|
||
INT cfoodRemain; /* Amount of food left to eat */
|
||
INT cfoodUsed; /* Amount of food eaten */
|
||
INT cLevel = 0; /* current level */
|
||
|
||
INT cLives = cLivesStart; /* Count of Lives */
|
||
|
||
#define idirMax 10
|
||
DIR rgdir[idirMax];
|
||
|
||
INT idirCurr;
|
||
INT idirLast;
|
||
|
||
INT ctickMove;
|
||
INT ctickMoveMac = 4;
|
||
|
||
INT ctickTime;
|
||
INT ctickTimeMac = 1;
|
||
|
||
#define cTimeLeftMax dxpTime
|
||
INT cTimeLeft = cTimeLeftMax;
|
||
|
||
#define lenStart 7
|
||
|
||
extern INT score;
|
||
extern BOOL fWipe;
|
||
|
||
INT rgtickSkill[3] = {5, 3, 1};
|
||
|
||
BLK mpdirdirblk[4][4] =
|
||
{
|
||
{blkBodyNS, blkBodySE, blkNull, blkBodySW}, /* N */
|
||
{blkBodyNW, blkBodyEW, blkBodySW, blkNull }, /* E */
|
||
{blkNull, blkBodyNE, blkBodyNS, blkBodyNW}, /* S */
|
||
{blkBodyNE, blkNull, blkBodySE, blkBodyEW} /* W */
|
||
};
|
||
|
||
|
||
#define IncIDir(idir) (idir = (idir+1) % idirMax)
|
||
|
||
#define BlkTailFromDir(dir) (blkTailN + (dir))
|
||
#define BlkHeadFromDir(dir) (blkHeadN + (dir))
|
||
#define DirFromBlk(blk) ((DIR) ((blk) & 0x0003))
|
||
|
||
|
||
/*** Global/External Variables ***/
|
||
|
||
extern STATUS status;
|
||
extern PREF Preferences;
|
||
extern BOOL fUpdateIni;
|
||
extern INT cMoveScore;
|
||
|
||
|
||
|
||
|
||
/****** C H A N G E P O S B L K ******/
|
||
|
||
VOID ChangePosBlk(POS pos, BLK blk)
|
||
{
|
||
mpposblk[pos] = blk;
|
||
DisplayPos(pos);
|
||
}
|
||
|
||
|
||
/****** D R O P F O O D ******/
|
||
|
||
POS DropFood(VOID)
|
||
{
|
||
POS pos;
|
||
|
||
while (mpposblk[pos = Rnd(posMax)] != blkNull)
|
||
;
|
||
mpposblk[pos] = blkFood;
|
||
|
||
return pos;
|
||
}
|
||
|
||
|
||
/****** P O S F R O M P O S D I R ******/
|
||
|
||
POS PosFromPosDir(POS pos, DIR dir)
|
||
{
|
||
switch (dir)
|
||
{
|
||
case dirN:
|
||
return (pos - xMax);
|
||
|
||
case dirE:
|
||
return (pos + 1);
|
||
|
||
case dirS:
|
||
return (pos + xMax);
|
||
|
||
case dirW:
|
||
return (pos - 1);
|
||
|
||
#ifdef DEBUG
|
||
default:
|
||
Oops("PosFromPosDir: Invalid Direction");
|
||
return pos;
|
||
#endif
|
||
}
|
||
|
||
// program should not reach this section of code!
|
||
return pos;
|
||
}
|
||
|
||
/****** D I R F R O M P O S P O S ******/
|
||
|
||
DIR DirFromPosPos(POS posSrc, POS posDest)
|
||
{
|
||
INT dpos = posDest-posSrc;
|
||
|
||
if (dpos == xMax)
|
||
return dirS;
|
||
|
||
else if (dpos == 1)
|
||
return dirE;
|
||
|
||
else if (dpos == -xMax)
|
||
return dirN;
|
||
|
||
#ifndef DEBUG
|
||
else
|
||
return dirW;
|
||
#else
|
||
else if (dpos == -1)
|
||
return dirW;
|
||
|
||
else
|
||
Oops("DirFromPosPos: Invalid Direction");
|
||
return dirN;
|
||
#endif
|
||
}
|
||
|
||
|
||
/****** B L K T A I L F R O M B L K B L K ******/
|
||
|
||
BLK BlkTailFromBlkBlk(BLK blkSrc, BLK blkDest)
|
||
{
|
||
if (blkDest == blkBodyNS || blkDest == blkBodyEW)
|
||
return blkSrc;
|
||
|
||
if (blkDest == blkBodyNE)
|
||
if (blkSrc == blkTailW)
|
||
return blkTailN;
|
||
else
|
||
return blkTailE;
|
||
|
||
else if (blkDest == blkBodySE)
|
||
if (blkSrc == blkTailW)
|
||
return blkTailS;
|
||
else
|
||
return blkTailE;
|
||
|
||
else if (blkDest == blkBodySW)
|
||
if (blkSrc == blkTailE)
|
||
return blkTailS;
|
||
else
|
||
return blkTailW;
|
||
|
||
else /* if (blkDest == blkBodyNW) */
|
||
if (blkSrc == blkTailE)
|
||
return blkTailN;
|
||
else
|
||
return blkTailW;
|
||
}
|
||
|
||
|
||
|
||
|
||
/****** D O C H A N G E D I R ******/
|
||
|
||
VOID DoChangeDir(DIR dir)
|
||
{
|
||
if (!fHead)
|
||
return;
|
||
|
||
if (((dir+2) % 4) == rgdir[idirLast]) /* Don't allow about faces */
|
||
return;
|
||
|
||
if (IncIDir(idirLast) == idirCurr) /* Watch for overflow */
|
||
{
|
||
if (--idirLast < 0)
|
||
idirLast = idirMax-1;
|
||
return;
|
||
}
|
||
|
||
rgdir[idirLast] = dir;
|
||
}
|
||
|
||
|
||
/****** D O C H A N G E R E L D I R ******/
|
||
|
||
VOID DoChangeRelDir(DIR dirRel)
|
||
{
|
||
if ( (dirRel = rgdir[idirLast] + dirRel) < 0)
|
||
dirRel = dirW;
|
||
else if (dirRel > dirW)
|
||
dirRel = dirN;
|
||
|
||
DoChangeDir(dirRel);
|
||
}
|
||
|
||
|
||
/****** K I L L S N A K E ******/
|
||
|
||
VOID KillSnake(VOID)
|
||
{
|
||
fHead = fTail = fFalse;
|
||
fPlum = fFalse;
|
||
|
||
if (cLives--)
|
||
{
|
||
PlayTune(TUNE_HITHEAD);
|
||
StartLevel();
|
||
}
|
||
else
|
||
{
|
||
PlayTune(TUNE_LOSEGAME);
|
||
cLives = 0;
|
||
ClrStatusPlay();
|
||
if (score > Preferences.HiScore)
|
||
{
|
||
/* Congrats, etc. */
|
||
Preferences.HiScore = score;
|
||
Preferences.HiLevel = cLevel;
|
||
fUpdateIni = fTrue;
|
||
}
|
||
DisplayGameOver();
|
||
}
|
||
}
|
||
|
||
|
||
/****** D E C T I M E ******/
|
||
|
||
/* Decrement time left */
|
||
|
||
VOID DecTime(VOID)
|
||
{
|
||
if (--cTimeLeft < 0)
|
||
{
|
||
INT i;
|
||
for (i = 0; i < 3; i++)
|
||
{
|
||
DisplayPos(DropFood());
|
||
cfoodRemain++;
|
||
}
|
||
cTimeLeft = cTimeLeftMax;
|
||
DisplayTime();
|
||
}
|
||
else
|
||
UpdateTime();
|
||
}
|
||
|
||
|
||
|
||
/****** D O M O V E ******/
|
||
|
||
VOID DoMove(VOID)
|
||
{
|
||
POS posPrev;
|
||
BLK blkPrev;
|
||
DIR dir;
|
||
|
||
if (fHead)
|
||
{
|
||
if (posHead == posLeave && fExit)
|
||
{
|
||
ChangePosBlk(posHead, blkBodyNS);
|
||
fHead = fFalse;
|
||
}
|
||
else
|
||
{
|
||
/* Check heading/direction */
|
||
|
||
if ((idirCurr != idirLast) && (posHead != posEnter))
|
||
IncIDir(idirCurr);
|
||
|
||
/* Change head into body */
|
||
|
||
blkPrev = mpposblk[posPrev = posHead];
|
||
posHead = PosFromPosDir(posPrev, dir = rgdir[idirCurr]);
|
||
|
||
if (mpposblk[posHead] != blkNull)
|
||
{
|
||
if (mpposblk[posHead] < blkHeadN) /*** EAT FOOD ***/
|
||
{
|
||
AddScore(1);
|
||
cTimeLeft = cTimeLeftMax;
|
||
DisplayTime();
|
||
|
||
if (--cfoodRemain == 0)
|
||
{
|
||
fExit = fTrue;
|
||
ctickTime = tickNil;
|
||
cTimeLeft = cTimeLeftMax;
|
||
DisplayTime();
|
||
ChangePosBlk(posLeave, blkNull);
|
||
}
|
||
fTail = fFalse;
|
||
cDelayTail += 4;
|
||
}
|
||
else
|
||
{
|
||
KillSnake();
|
||
return;
|
||
}
|
||
}
|
||
|
||
ChangePosBlk(posPrev, mpdirdirblk[DirFromBlk(blkPrev)][dir]);
|
||
ChangePosBlk(posHead, BlkHeadFromDir(dir));
|
||
}
|
||
|
||
}
|
||
else if (cDelayHead)
|
||
{
|
||
if (--cDelayHead == 0)
|
||
{
|
||
ChangePosBlk(posHead, blkHeadN);
|
||
fHead = fTrue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ctickMove = 1; /* Must be leaving (fExit == fTrue) */
|
||
}
|
||
|
||
if (fTail)
|
||
{
|
||
if (posTail == posLeave)
|
||
{
|
||
ChangePosBlk(posTail, blkNull);
|
||
fTail = fFalse;
|
||
|
||
if ((++cLevel % lvlMax) == 0)
|
||
{
|
||
if (ctickMoveMac > 1)
|
||
ctickMoveMac--;
|
||
PlayTune(TUNE_WINGAME);
|
||
}
|
||
else
|
||
PlayTune(TUNE_WINLEVEL);
|
||
|
||
StartLevel();
|
||
AddScore(10);
|
||
}
|
||
|
||
else
|
||
{
|
||
/* Remove old tail */
|
||
|
||
blkPrev = mpposblk[posPrev = posTail];
|
||
if (posTail == posEnter)
|
||
ChangePosBlk(posPrev, blkWallEW); /* Close entrance */
|
||
else
|
||
ChangePosBlk(posPrev, blkNull);
|
||
|
||
/* Display new tail */
|
||
|
||
posTail = PosFromPosDir(posPrev, DirFromBlk(blkPrev));
|
||
|
||
ChangePosBlk(posTail, BlkTailFromBlkBlk(blkPrev, mpposblk[posTail]));
|
||
}
|
||
}
|
||
else if (cDelayTail)
|
||
{
|
||
if (--cDelayTail == 0)
|
||
{
|
||
if (posTail == posEnter)
|
||
{
|
||
ChangePosBlk(posTail, blkTailN);
|
||
}
|
||
fTail = fTrue;
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
/****** F K I L L B O U N C E ******/
|
||
|
||
BOOL FKillBounce(POS pos)
|
||
{
|
||
if (mpposblk[pos] != blkNull)
|
||
{
|
||
if (pos == posHead)
|
||
KillSnake();
|
||
return fTrue;
|
||
}
|
||
else
|
||
if (pos == posLeave) /* Don't go into exit */
|
||
return fTrue;
|
||
else
|
||
return fFalse;
|
||
}
|
||
|
||
|
||
/****** D O T I M E R ******/
|
||
|
||
VOID DoTimer(VOID)
|
||
{
|
||
BOOL fBounce = 0; /* Variable - there must be a better way */
|
||
|
||
if (cMoveScore != 0)
|
||
MoveScore();
|
||
|
||
if (!FPlay())
|
||
return;
|
||
|
||
if (--ctickMove == 0)
|
||
{
|
||
ctickMove = ctickMoveMac;
|
||
DoMove();
|
||
|
||
if (fPlum)
|
||
{
|
||
if (FKillBounce(posPlum + offPlumNS))
|
||
{
|
||
offPlumNS = -offPlumNS;
|
||
fBounce = 1;
|
||
}
|
||
if (FKillBounce(posPlum + offPlumEW))
|
||
{
|
||
offPlumEW = -offPlumEW;
|
||
fBounce = 2;
|
||
}
|
||
|
||
if (!fBounce)
|
||
{
|
||
if (FKillBounce(posPlum + offPlumNS + offPlumEW))
|
||
{
|
||
offPlumNS = -offPlumNS;
|
||
offPlumEW = -offPlumEW;
|
||
}
|
||
}
|
||
else if (FKillBounce(posPlum+offPlumNS + offPlumEW))
|
||
{
|
||
if (fBounce == 1)
|
||
offPlumEW = -offPlumEW;
|
||
else
|
||
offPlumNS = -offPlumNS;
|
||
}
|
||
|
||
if (fPlum && (mpposblk[posPlum + offPlumNS + offPlumEW] == blkNull))
|
||
{
|
||
ChangePosBlk(posPlum, blkNull);
|
||
posPlum += offPlumNS + offPlumEW;
|
||
ChangePosBlk(posPlum, blkPlum);
|
||
}
|
||
}
|
||
|
||
}
|
||
else if (ctickMove < -50 && (cMoveScore==0)) /* This happens at the start of a game */
|
||
{
|
||
fPlum = (cLevel >= lvlMax);
|
||
ctickMove = ctickMoveMac;
|
||
ctickTime = ctickTimeMac;
|
||
cTimeLeft = cTimeLeftMax;
|
||
fWipe = fFalse;
|
||
SetLevelColor();
|
||
DisplayScreen();
|
||
}
|
||
|
||
if (--ctickTime == 0)
|
||
{
|
||
ctickTime = ctickTimeMac;
|
||
DecTime();
|
||
}
|
||
}
|
||
|
||
|
||
/****** S T A R T L E V E L *******/
|
||
|
||
VOID StartLevel(VOID)
|
||
{
|
||
fPlum = fFalse;
|
||
|
||
cTimeLeft = cTimeLeftMax;
|
||
|
||
DisplayLevelNum();
|
||
|
||
SetupLevelData();
|
||
|
||
if (cLevel >= lvlMax)
|
||
{
|
||
offPlumNS = xMax;
|
||
offPlumEW = 1;
|
||
posPlum = 4*xMax + 3;
|
||
while (mpposblk[posPlum] != blkNull)
|
||
posPlum--;
|
||
mpposblk[posPlum] = blkPlum;
|
||
}
|
||
|
||
/* Distribute Food */
|
||
|
||
cfoodUsed = cfoodRemain = 10;
|
||
while (cfoodUsed--)
|
||
{
|
||
DropFood();
|
||
}
|
||
|
||
|
||
/* Setup player position */
|
||
|
||
fTail = fHead = fFalse;
|
||
|
||
cDelayHead = 3;
|
||
cDelayTail = lenStart;
|
||
|
||
posTail = posHead = posEnter;
|
||
|
||
ctickMove = -1; /* Indicate Starting Level */
|
||
ctickTime = -1;
|
||
|
||
rgdir[idirCurr=idirLast=0] = dirN;
|
||
|
||
ClrStatusIcon();
|
||
SetStatusPlay();
|
||
}
|
||
|
||
|
||
/****** S T A R T G A M E *******/
|
||
|
||
VOID StartGame(INT lvl)
|
||
{
|
||
cLevel = lvl;
|
||
cLives = cLivesStart;
|
||
|
||
ctickMoveMac = max(0,rgtickSkill[Preferences.skill] - cLevel/lvlMax);
|
||
ctickTimeMac = Preferences.skill ? 1 : 2;
|
||
|
||
ResetScore();
|
||
DisplayScore();
|
||
StartLevel();
|
||
}
|
||
|