
| "Thak" revolves around our central character, namely
a caveman named Thak (imagine that). The game itself is an overhead,
real-time strategy game, similar to that of the Command and Conquer, StarCraft
genre. Each player begins the game controlling Thak, and a hut where
cavemen can be trained. Thak himself is not a warrior. He builds
things. Warriors carry clubs and they do all the attacking.
Thak can build walls. A player can command up to five cavemen at
a time, and cavemen can be replaced as they are eliminated.
The objective of the game is to protect Thak and kill the other player's Thak. There is no mining in this game, so to speak. You don't collect resources. We implemented all of our original programming goals, as
listed below. Due to time constraints, however, we were unable to explore
our optional
programming goals. We are quite happy to say, though, that the game
is fully functional and playable.
|
Known Bugs in Thak as of handin date, December 8, 1998:
-producing 5th caveman sometimes causes opponent
to lock up.
-Occasional screen flicker seems to make cavemen
disappear for short periods of time. May be due to net lag.
-Thak always exits building wall to the upper left,
occasionally overstepping collision detection.
General Network Structure

| The first player to log in creates an instance of "ThakTheServer."
This player is assigned player number 0, which is equivalent to being player
one. The second player is then, naturally player two, and is assigned
player number 1. Each player broadcasts the packet containing their
player structure. Upon receiving a packet, the client checks the
player number who sent it (first byte in packet). If it is his own
packet, it is discarded. If it is the opposing player, it is stored
in the OtherUnits structure. The client only accepts packets from
his specific opponent. At this point the clients enter the main game loop,
in which they:
1) Receive Packet from the server. 2) Check if Thak is alive. If he's not, the game is over and we jump to the game over sequence. 3) Client draws the screen. 4) Clients create new units and buildings. 5) Client moves his existing units. 6) If units were attacked health is updated, as are caveman statuses. 7) Each client updates his unit structure. 8) Sounds are played. 9) Each client broadcasts their unit structure.. 10) Loops back to 1) |

Each double word in the game grid is constructed as shown above.
The first byte represents the type of terrain.
(0=hut, 3=grass, 4=wall, 5=rock)
The next byte represents the status of that object.
(Applied to wall to determine which corner).
The next byte was used to represent the health of the wall,
but was later eliminated as we removed the ability to attack walls.
The last byte is not used.
CONSTANTS (on both Server and Client)
Variables (on Server)
;Structures
UnitStructure STRUC
Type db ? ;unit
type 0=Thak 1=Caveman 2=Hut
3=Wall
Status db ? ;Status indicator
i.e. player direction, digger position If = 0FFh, indicates unit doesn't
exist.
PosX dw ? ;X coordinate
of this unit
PosY dw ? ;Y coordinate
of this unit
Health db ? ;Health of
this unit
CurrentG dw ? ;Current
grid position of this unit
DestinationG dw ?
;destination grid position for this unit.
ENDS
P1Units STRUC
PlayerNumber db 1
Hut UnitStructure <2,0,HUT1XSTART,HUT1YSTART,HUTHEALTH,HUT1GRIDSTART,
HUT1GRIDSTART>
Thak UnitStructure <0,2,THAK1XSTART,THAK1YSTART,THAKHEALTH,THAK1GRIDSTART,
THAK1GRIDSTART>
Caveman0 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman1 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman2 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman3 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman4 UnitStructure <1,0FFh,0,0,0,0,0>
NewWall UnitStructure <3,0FFh,0,0,0,0,0>
;indicates a new wall has been created and where, if needed.
ENDS
P2Units STRUC
PlayerNumber db 2
Hut UnitStructure <2,0,HUT2XSTART,HUT2YSTART,HUTHEALTH,HUT2GRIDSTART,
HUT2GRIDSTART>
Thak UnitStructure <0,2,THAKXSTART,THAKYSTART,THAKHEALTH,THAK2GRIDSTART,
THAK2GRIDSTART>
Caveman0 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman1 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman2 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman3 UnitStructure <1,0FFh,0,0,0,0,0>
Caveman4 UnitStructure <1,0FFh,0,0,0,0,0>
NewWall UnitStructure <3,0FFh,0,0,0,0,0>
;indicates a new wall has been created and where, if needed.
ENDS
Variables (on Client)
;Segments
WAVSeg segment 'DATA1'
;segment holds wave data
WaveBuffer DB 65535 dup(?)
WAVSeg ends
MIDISeg segment 'DATA2'
;segment holds midi data
MIDIBuffer db 65535 dup(?)
MIDISeg ends
SBSeg segment 'DATA3'
;segment holds screen data
ScreenBuffer db 65535 dup(?) ;blasted from here to the screen
SBSeg ends
FontSeg segment 'DATA4'
;used by load pcx holds the fontmap (like in mp4)
FontMap db 65535 dup(?)
FontSeg ends
SCRSeg segment 'DATA5'
;used by load PCX holds files while
Scratchpad db 65535 dup(?) ;they are decoded
SCRSeg ends
DrawSeg segment 'DATA6'
;holds map for things to draw
DrawMap db 65535 dup(?) ; buildings units terraine
DrawSeg ends
StarSeg segment 'DATA7'
;holds Star field for intro
StarMap db 65535 dup(?)
StarSeg ends
DrawFile db 'units2.pcx',0
;filename of PCX file with building images.
CBarFile db 'Cbarmap.pcx',0
;filename of PCX file with control bar images.
MainMenuFile db 'mainmenu.pcx',0 ;filename of MainMenu
PCX file
Inst1File db 'Inst1.pcx',0
;instruction one file
Inst2File db 'Inst2.pcx',0
;instruction two file
WaitFile db 'waiting.pcx',0
;waiting file
Fire1File db 'fire1.pcx',0
;Fire1 anim
Fire2File db 'fire2.pcx',0
;Fire2 anim
Fire3File db 'fire3.pcx',0
;Fire3 anim
StarsFile db 'stars.pcx',0
;Star field
Head1File db 'Head1.pcx',0
Head2File db 'Head2.pcx',0
Head3File db 'Head3.pcx',0
Head4File db 'Head4.pcx',0
;Head 4 file
Head5File db 'Head5.pcx',0
;Head 5 file
Head6File db 'Head6.pcx',0
;Head 6 file
ThakFile db 'thak.pcx',0
;Thak
;NOTE: also need variables with filenames for .WAV files and MIDI files
;(for MIDPAK).
; FontMap is a 320x200 PCX File containing 8x8 letters
; ABCDEFGHIJKLMNOPQRSTUVWXYZ
; abcdefghijklmnopqrstuvwxyz
; 01234567890
;
; Letters is a 256-word lookup table that
; maps each ASCII value to a location in FontMap
; Our program need only map letters, digits, space, and period.
; As used in MP4.
Letters dw 32 dup ((320*166)+(8*11))
dw
(320*166)+(8*12) ; ' '
dw
13 dup ((320*166)+(8*11))
dw
(320*166)+(8*10) ; '.'
dw
(320*166)+(8*11)
dw
(320*166)+(8*0) ; '0'
dw
(320*166)+(8*1) ; '1'
dw
(320*166)+(8*2) ; '2'
dw
(320*166)+(8*3) ; '3'
dw
(320*166)+(8*4) ; '4'
dw
(320*166)+(8*5) ; '5'
dw
(320*166)+(8*6) ; '6'
dw
(320*166)+(8*7) ; '7'
dw
(320*166)+(8*8) ; '8'
dw
(320*166)+(8*9) ; '9'
dw
7 dup ((320*166)+(8*11))
dw
(320*150)+(8*0) ; 'A'
dw
(320*150)+(8*1) ; 'B'
dw
(320*150)+(8*2) ; 'C'
dw
(320*150)+(8*3) ; 'D'
dw
(320*150)+(8*4) ; 'E'
dw
(320*150)+(8*5) ; 'F'
dw
(320*150)+(8*6) ; 'G'
dw
(320*150)+(8*7) ; 'H'
dw
(320*150)+(8*8) ; 'I'
dw
(320*150)+(8*9) ; 'J'
dw
(320*150)+(8*10) ; 'K'
dw
(320*150)+(8*11) ; 'L'
dw
(320*150)+(8*12) ; 'M'
dw
(320*150)+(8*13) ; 'N'
dw
(320*150)+(8*14) ; 'O'
dw
(320*150)+(8*15) ; 'P'
dw
(320*150)+(8*16) ; 'Q'
dw
(320*150)+(8*17) ; 'R'
dw
(320*150)+(8*18) ; 'S'
dw
(320*150)+(8*19) ; 'T'
dw
(320*150)+(8*20) ; 'U'
dw
(320*150)+(8*21) ; 'V'
dw
(320*150)+(8*22) ; 'W'
dw
(320*150)+(8*23) ; 'X'
dw
(320*150)+(8*24) ; 'Y'
dw
(320*150)+(8*25) ; 'Z'
dw
6 dup ((320*166)+(8*11))
dw
(320*158)+(8*0) ; 'a'
dw
(320*158)+(8*1) ; 'b'
dw
(320*158)+(8*2) ; 'c'
dw
(320*158)+(8*3) ; 'd'
dw
(320*158)+(8*4) ; 'e'
dw
(320*158)+(8*5) ; 'f'
dw
(320*158)+(8*6) ; 'g'
dw
(320*158)+(8*7) ; 'h'
dw
(320*158)+(8*8) ; 'i'
dw
(320*158)+(8*9) ; 'j'
dw
(320*158)+(8*10) ; 'k'
dw
(320*158)+(8*11) ; 'l'
dw
(320*158)+(8*12) ; 'm'
dw
(320*158)+(8*13) ; 'n'
dw
(320*158)+(8*14) ; 'o'
dw
(320*158)+(8*15) ; 'p'
dw
(320*158)+(8*16) ; 'q'
dw
(320*158)+(8*17) ; 'r'
dw
(320*158)+(8*18) ; 's'
dw
(320*158)+(8*19) ; 't'
dw
(320*158)+(8*20) ; 'u'
dw
(320*158)+(8*21) ; 'v'
dw
(320*158)+(8*22) ; 'w'
dw
(320*158)+(8*23) ; 'x'
dw
(320*158)+(8*24) ; 'y'
dw
(320*158)+(8*25) ; 'z'
dw
132 dup ((320*166)+(8*11))
Units dw (320*0)+(30*0)
;position of caveman up, position one (CU1)
dw
(320*0)+(30*1) ;CR1
dw
(320*0)+(30*2) ;CD1
dw
(320*0)+(30*3) ;CL1
dw
(320*0)+(30*4) ;CU2
dw
(320*0)+(30*5) ;CR2
dw
(320*0)+(30*6) ;CD2
dw
(320*0)+(30*7) ;CL2
dw
(320*0)+(30*8) ;position of caveman attack position up (CAU)
dw
(320*0)+(30*9) ;CAR
dw
(320*30)+(30*0) ;CAD
dw
(320*30)+(30*1) ;CAL
dw
(320*30)+(30*2) ;position of thak up, position one (TU1)
dw
(320*30)+(30*3) ;TR1
dw
(320*30)+(30*4) ;TD1
dw
(320*30)+(30*5) ;TL1
dw
(320*30)+(30*6) ;TU2
dw
(320*30)+(30*7) ;TR2
dw
(320*30)+(30*8) ;TD2
dw
(320*30)+(30*9) ;TL2
dw
(320*60)+(30*0) ;Location of Digger animated position one
dw
(320*60)+(30*2) ;Location of Digger animated position two
dw
(320*60)+(60*2) ;Location of Hut
dw
(320*60)+(60*3) ;Location of Wall, Top Left corner
dw
(320*60)+(30*7) ;Top right corner
dw
(320*90)+(60*3) ;Bot Left corner
dw
(320*90)+(30*7) ;Bot Right corner
Terrain dw (320*120)+(30*0) ;location
of grass
dw
(320*120)+(30*1) ;location of rock
CBarLetters dw 65 dup ((320*174)+(8*26))
dw
(320*174)+(8*0) ; 'A' (letters for control bar)
dw
(320*174)+(8*1) ; 'B'
dw
(320*174)+(8*2) ; 'C'
dw
(320*174)+(8*3) ; 'D'
dw
(320*174)+(8*4) ; 'E'
dw
(320*174)+(8*5) ; 'F'
dw
(320*174)+(8*6) ; 'G'
dw
(320*174)+(8*7) ; 'H'
dw
(320*174)+(8*8) ; 'I'
dw
(320*174)+(8*9) ; 'J'
dw
(320*174)+(8*10) ; 'K'
dw
(320*174)+(8*11) ; 'L'
dw
(320*174)+(8*12) ; 'M'
dw
(320*174)+(8*13) ; 'N'
dw
(320*174)+(8*14) ; 'O'
dw
(320*174)+(8*15) ; 'P'
dw
(320*174)+(8*16) ; 'Q'
dw
(320*174)+(8*17) ; 'R'
dw
(320*174)+(8*18) ; 'S'
dw
(320*174)+(8*19) ; 'T'
dw
(320*174)+(8*20) ; 'U'
dw
(320*174)+(8*21) ; 'V'
dw
(320*174)+(8*22) ; 'W'
dw
(320*174)+(8*23) ; 'X'
dw
(320*174)+(8*24) ; 'Y'
dw
(320*174)+(8*25) ; 'Z'
UnitPortraits dw (320*5)+5
;should never be used, 0 represents no unit selected.
dw
(320*90)+(43*2) ;location of Hut portrait
dw
(320*90)+(43*1) ;location of Thak portrait
dw
5 dup ((320*90)+(43*0)) ;location of Caveman portrait
UnitNames dw (320*90)+(43*3)
;never used. 0 reps no unit selected.
dw
(320*111)+(43*3) ;location of 'Hut'
dw
(320*90)+(43*3)+93 ;location of 'Thak'
dw
(320*90)+(43*3) ;location of 'Caveman'
;Sound Variables
;DMA
db 1
;contains DMA for sound
;IRQ
db 5
;IRQ for sound
;Base
dw 220h
;Base contains Port Address for sound
crlf db
CR,LF,'$' ; DOS uses carriage return + Linefeed for new line
CrashSound db
'hitface1.wav',0 ; Filename of crash sound
WavLength
dw 0
Sample db
'tarzan1.wav',0
Mario db
'Mario.xmi',0
MarioLength dw 11956
island db
'Isld.xmi',0
isLn dw
6384
;real midi vars
MIDOne
db 'MIDOne.xmi', 0
MIDOneLn
dw 13524
MIDTwo
db 'MIDTwo.xmi', 0
MIDTwoLn
dw 14890
MIDThr
db 'MIDThr.xmi', 0
MIDThrLn
dw 8524
MIDFour
db 'MIDFour.xmi', 0
MIDFourLn
dw 5870
MIDFive
db 'MIDFive.xmi', 0
MIDFiveLN
dw 1568
MIDSix
db 'MIDSix.xmi', 0
MIDSixLn
dw 15830
;real wav vars
ThakDie
db 0
;flags fo tell if a sound needs to be played
NewDest
db 0
BuildCrsh
db 0
CvDie
db 0
HutHit
db 0
Hit
db 0
NewCv
db 0
ThakBld
db 0
ThakDieSnd
db 'SomeFile.wav', 0
NewDestSnd
db 'SomeFile.wav', 0
BuildCrshSnd
db 'SomeFile.wav', 0
CvDieSnd
db 'SomeFile.wav', 0
HutHitSnd
db 'SomeFile.wav', 0
HitSnd
db 'hitface1.wav', 0
NewCvSnd
db 'SomeFile.wav', 0
ThakBldSnd
db 'SomeFile.wav', 0
CvSelSnd
db 'tarzan1.wav', 0
ThakSelSnd
db 'tarzan1.wav', 0
HutSelSnd
db 'SomeFile.wav', 0
TapGlassSnd
db 'SomeFile.wav', 0
;sampling vars
SampRate
db ?
TtwoSamp
db 206
ElevSamp
db 165
EightSamp
db 131
SAMPLING
db 0
;Graphics Variables
ViewPortX
dw 0 ;X coordinate of current view
screen.
ViewPortY
dw 0 ;Y coordinate of current view
screen.
HutBurn
db 1
;Input Variables
oldKeyV
dd ? ;holds old key and mouse
handler addresses
MouseX
dw 0 ;holds Mouse X and Y coordinates
(in relation to current screen). 0 <= X <= 319
MouseY
dw 0 ;0 <= Y <= 199
LeftB
db 0 ;Flags to indicate if Left
or Right mouse buttons have been clicked.
RightB
db 0
Ipressed
db 0 ;Flags to indicate different
Keystrokes, set by Keyboard handler.
Jpressed
db 0
Mpressed
db 0
Xpressed
db 0
Uppressed
db 0
Downpressed
db 0
RightPressed
db 0
LeftPressed
db 0
EscPressed
db 0
BPressed
db 0
SpcPressed
db 0
;GamePlay Variables
MyKills
dw 0
;stores kills for this player
MyLosses
dw 0
;stores deaths for this player (equal to kills for other player)
PlayerSelected db
0 ;indicates
if a unit is selected, and if so, which one.1=Thak,2=Caveman0,etc. 0=none
;0=none 1=Hut 2=Thak 3,4,5,6,7=Caveman0-4
WallBuild
db 0
;timer for construction of a wall.
CavemanBuild
db 0
;timer for creation of a caveman.
CurrentGX
db ?
CurrentGY
db ?
DestinationGX db
?
DestinationGY db
?
StateTimer
db 0
CavemanOffset dw
0 ;offset
of caveman which is being built
GameGrid
dd 3h
dd 3h
dd 5
dd 19 dup (3)
dd 3h
dd 3h
;dd 20 dup (3) ;game grid recieved
from server.
dd 80 dup (3)
dd 5
dd 120 dup (3)
dd 5
dd 50 dup (3)
dd 5
dd 30 dup (3)
dd 5
dd 72 dup (3)
dd 00000004h
dd 00000104h
dd 20 dup (3)
dd 00000304h
dd 00000204h
dd 3 dup (3)
dd 5
dd 34 dup (3)
;Structures
UnitStructure
STRUCT
UnitType
db ? ;unit type 0=Thak
1=Caveman 2=Hut 3=Wall
Status
db ? ;Status indicator i.e. player
direction, digger position
PosX
dw ? ;X coordinate of this unit
PosY
dw ? ;Y coordinate of this unit
Health
db ? ;Health of this unit
CurrentG
dw ? ;Current grid position of this
unit
DestinationG
dw ? ;destination grid position for
this unit.
UnitStructure ENDS
PlayerStructure STRUCT
PlayerNumber
db 0FFh ;contains 1 if player 1, 2
if player 2
Hut
UnitStructure <2,0,30,60,30,45,45>
Thak
UnitStructure <0,02h,120,60,15,48,48>
Caveman0
UnitStructure <1,0FFh,0,0,15,35,0>
Caveman1
UnitStructure <1,0FFh,0,0,15,100,0>
Caveman2
UnitStructure <1,0FFh,0,0,15,156,0>
Caveman3
UnitStructure <1,0FFh,0,0,15,200,0>
Caveman4
UnitStructure <1,0FFh,0,0,15,336,0>
NewWall
UnitStructure <3,0FFh,0,0,0,0,0> ;indicates a new
wall has been created and where, if needed.
GOver
db 0
PlayerStructure ENDS
MyUnits PlayerStructure <>
OtherUnits PlayerStructure <>
The Game Main Function (this is the pseudocode for our game main sequence)
GameMain
CheckSound
RegisterXMIDI
InstThakKey
LoadPCXFirst ;loads first image and sets palette
Use LoadPCX to load fontmap and drawmap
Display IntroSequence
MainMenu:
GameMM
if X pressed jump to End
if J pressed jump to ConnectToNetwork
if I pressed jump to Instructions
Instructions:
GameInstructions
Jump to MainMenu
ConnectToNetwork:
ClientPacketSend
Wait for server packet to start game
StartMIDI
GameLoop:
ClientPacketRecieve
poll for packet
This will contain the opposing player's structure.
CheckESCPressed
if so jump to EndSequence
LifeCheck
if Thack is dead jump to EndSequence
InitBuf
DrawGameScreen
uses DrawGSObject, DrawGSUnits, DrawOwnership
DrawControlBar
uses DrawMinimap, DrawSelectedUnit, DrawSUHealth,
DrawSUName, DrawHealthTick, DrawMiniBlock,
DrawCavemanBuild.
DrawScreen
ScrollScreen
check if screen needs to be scrolled, if so change ViewPort X and Y
MouseCheck
Use mouse interrupt to obtain mouse position and click status.
MouseCalculate
Determine exact grid clicked, determine if unit selected or moved.
Play sounds as needed.
BuildCaveMan
Check if new caveman being made (hut selected, b pressed)
BuildNewWall
Will Call BuildWall if a new wall needs to be built
MoveUnit
uses CheckGridPos, CheckGridFit, MoveUnitHelper
Check for Attack situations and damage
uses CheckMyPain, CheckCaveman0
ClientPacketSend
jump to GameLoop
EndSequence:
StopMIDI
GameOverSequence
jump to End
End:
DeInstKey
GameMain endp