mirror of
https://github.com/goonstation/goonstation-2016.git
synced 2026-07-11 17:12:19 +01:00
640 lines
18 KiB
Plaintext
640 lines
18 KiB
Plaintext
//CONTENTS:
|
|
//Robustris
|
|
//Robustris block datum
|
|
//Arcade game
|
|
//CodeBreaker (aka Mastermind)
|
|
|
|
#define SETUP_BLOCKS_HORIZ 10
|
|
#define SETUP_BLOCKS_VERT 12
|
|
#define SETUP_BLOCK_COLOR "565D4B"
|
|
#define SETUP_PLAYFIELD_COLOR "7A856A"
|
|
#define SETUP_ROTATE_DELAY 5
|
|
|
|
/datum/computer/file/pda_program/robustris
|
|
name = "Robustris"
|
|
size = 6
|
|
setup_use_process = 1
|
|
var/tmp/list/blocks = null
|
|
var/tmp/list/blockmap = null
|
|
var/tmp/playing = 0
|
|
var/tmp/paused = 0
|
|
var/tmp/last_rotation = 0 //Don't bog down everything spinning blocks!!
|
|
var/tmp/highscore = 0
|
|
|
|
var/tmp/datum/robustris_block/active_block = null
|
|
|
|
init()
|
|
if(!src.blocks)
|
|
src.blocks = list()
|
|
src.clear_blocks()
|
|
src.playing = -1
|
|
|
|
return
|
|
|
|
/* new disposing() pattern should handle this. -singh
|
|
Del()
|
|
src.clear_blocks()
|
|
..()
|
|
*/
|
|
|
|
disposing()
|
|
src.clear_blocks()
|
|
|
|
src.blocks = null
|
|
if (src.blockmap)
|
|
src.blockmap.len = 0
|
|
src.blockmap = null
|
|
|
|
..()
|
|
|
|
return_text()
|
|
if(..())
|
|
return
|
|
|
|
var/dat = src.return_text_header()
|
|
|
|
dat += {"<center><b>Robustris<br>
|
|
Score:</b> [src.highscore]
|
|
<style type="text/css">
|
|
#playfield
|
|
{
|
|
border: 3px solid;
|
|
background-color: #[SETUP_PLAYFIELD_COLOR];
|
|
height: [16*(SETUP_BLOCKS_VERT+1)]px;
|
|
width: [(16*SETUP_BLOCKS_HORIZ)+6]px;
|
|
overflow-x: hidden;
|
|
overflow-y: hidden;
|
|
word-wrap: break-word;
|
|
position: relative;
|
|
}
|
|
.block
|
|
{
|
|
border: 1px solid
|
|
height: 16px;
|
|
width: 16px;
|
|
position: absolute;
|
|
background: #[SETUP_BLOCK_COLOR];
|
|
}
|
|
</style>
|
|
|
|
<div id="playfield"><tt>"}
|
|
for(var/datum/robustris_block/B in src.blocks)
|
|
dat += "<div class='block'style='bottom: [B.gridy*16]px;left: [B.gridx*16]px'><font color=#[SETUP_BLOCK_COLOR]>#</font></div>"
|
|
|
|
dat += "</tt></div>"
|
|
if(playing > -1)
|
|
if(paused)
|
|
dat += "<a href='byond://?src=\ref[src];resume=1'>Resume</a></b> | "
|
|
else
|
|
dat += "<a href='byond://?src=\ref[src];pause=1'>Pause</a></b>"
|
|
|
|
if(playing < 1)
|
|
dat += "<a href='byond://?src=\ref[src];newgame=1'>New Game</a></b>"
|
|
|
|
dat += {"</center>
|
|
|
|
<script language="JavaScript">
|
|
function passkey(){
|
|
var evar=window.event;
|
|
var ourKey=evar.keyCode? evar.keyCode : evar.charCode;
|
|
window.location="byond://?src=\ref[src];movedir=" + ourKey;
|
|
}
|
|
|
|
document.onkeypress=passkey
|
|
</script>
|
|
"}
|
|
|
|
return dat
|
|
|
|
process(var/speedup = 1)
|
|
if(..() || playing<1)
|
|
return
|
|
|
|
if(!active_block)
|
|
active_block = generate_new_block()
|
|
else
|
|
var/list/superblock = list(src.active_block) + src.active_block.related
|
|
var/datum/robustris_block/stop = null
|
|
for(var/datum/robustris_block/B in superblock)
|
|
var/next_y_position = B.gridy-1
|
|
if(next_y_position >= 0)
|
|
stop = blockmap[B.gridy][B.gridx+1]
|
|
if(stop)
|
|
break
|
|
else
|
|
stop = 1
|
|
break
|
|
|
|
if(stop)
|
|
var/game_over = 0
|
|
var/list/check_pass = list()
|
|
for(var/datum/robustris_block/B in superblock)
|
|
// drsingh for index out of bounds
|
|
if (blockmap.len < B.gridy + 1)
|
|
continue
|
|
|
|
var/list/blockx = blockmap[B.gridy + 1]
|
|
if (blockx.len < B.gridx + 1)
|
|
continue
|
|
|
|
blockmap[B.gridy+1][B.gridx+1] = B
|
|
if(B.gridy > SETUP_BLOCKS_VERT)
|
|
game_over = 1
|
|
|
|
if(!(B.gridy in check_pass))
|
|
check_pass += B.gridy
|
|
|
|
active_block = null
|
|
if(game_over)
|
|
src.playing = -1
|
|
else
|
|
check_completion(check_pass)
|
|
else
|
|
for(var/datum/robustris_block/B in superblock)
|
|
B.gridy--
|
|
|
|
|
|
src.master.updateSelfDialog()
|
|
if(speedup)
|
|
spawn(5) //Ugh the process loop for items is so slow most of the time
|
|
src.process(0)
|
|
|
|
return
|
|
|
|
Topic(href, href_list)
|
|
if(..())
|
|
return
|
|
|
|
if(href_list["movedir"])
|
|
if(!active_block || !playing)
|
|
return
|
|
var/movedir = href_list["movedir"]
|
|
switch(movedir)
|
|
if("97") //A
|
|
move_block(src.active_block, -1)
|
|
if("100") //D
|
|
move_block(src.active_block, 1)
|
|
if("115") //S
|
|
rotate_block(src.active_block, 1, -1)
|
|
if("119") //W
|
|
rotate_block(src.active_block, -1, 1)
|
|
if (ishuman(usr))
|
|
var/mob/living/carbon/human/H = usr
|
|
if (H.sims)
|
|
H.sims.affectMotive("fun", 0.5)
|
|
|
|
else if(href_list["newgame"])
|
|
src.clear_blocks()
|
|
src.playing = 1
|
|
src.paused = 0
|
|
|
|
else if(href_list["pause"])
|
|
src.playing = 0
|
|
src.paused = 1
|
|
|
|
else if(href_list["resume"])
|
|
src.playing = 1
|
|
src.paused = 0
|
|
|
|
src.master.add_fingerprint(usr)
|
|
src.master.updateSelfDialog()
|
|
return
|
|
|
|
proc
|
|
clear_blocks()
|
|
for(var/datum/robustris_block/B in src.blocks)
|
|
qdel(B)
|
|
|
|
if (isnull(src.blocks))
|
|
src.blocks = list()
|
|
|
|
src.blocks.len = 0
|
|
src.highscore = 0
|
|
|
|
//qdel(src.blockmap)
|
|
src.blockmap = new /list(SETUP_BLOCKS_VERT + 3, SETUP_BLOCKS_HORIZ)
|
|
return
|
|
|
|
generate_new_block()
|
|
var/datum/robustris_block/newblock = new /datum/robustris_block(rand(1,SETUP_BLOCKS_HORIZ-2),SETUP_BLOCKS_VERT)
|
|
|
|
var/block_type = pick(1,2,3,4,20;5)
|
|
switch(block_type)
|
|
if(1) //Square block
|
|
newblock.related += new /datum/robustris_block(newblock.gridx,newblock.gridy+1,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx+1,newblock.gridy+1,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx+1,newblock.gridy,newblock)
|
|
newblock.cannot_rotate = 1
|
|
if(2) //L block
|
|
newblock.related += new /datum/robustris_block(newblock.gridx + pick(1,-1),newblock.gridy,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx,newblock.gridy+1,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx,newblock.gridy+2,newblock)
|
|
if(3) //T block
|
|
newblock.related += new /datum/robustris_block(newblock.gridx+1,newblock.gridy,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx-1,newblock.gridy,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx,newblock.gridy+1,newblock)
|
|
if(4) //That stupid Z block
|
|
newblock.related += new /datum/robustris_block(newblock.gridx,newblock.gridy+1,newblock)
|
|
if(prob(50))
|
|
newblock.related += new /datum/robustris_block(newblock.gridx+1,newblock.gridy+1,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx+1,newblock.gridy+2,newblock)
|
|
else
|
|
newblock.related += new /datum/robustris_block(newblock.gridx-1,newblock.gridy+1,newblock)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx-1,newblock.gridy+2,newblock)
|
|
if(5) //The rare and treasured line block
|
|
for(var/i=1,i<=3,i++)
|
|
newblock.related += new /datum/robustris_block(newblock.gridx,newblock.gridy+i,newblock)
|
|
|
|
src.blocks += list(newblock) + newblock.related
|
|
|
|
return newblock
|
|
|
|
//Move a block left or right however far.
|
|
move_block(var/datum/robustris_block/theblock, magnitude=0)
|
|
if(!magnitude)
|
|
return 1
|
|
|
|
var/list/superblock = list(theblock) + theblock.related
|
|
for(var/datum/robustris_block/B in superblock)
|
|
var/new_x_position = B.gridx + magnitude
|
|
if(new_x_position < 0 || new_x_position >= SETUP_BLOCKS_HORIZ)
|
|
return 0
|
|
|
|
if(B.gridy < 0 || B.gridy >= SETUP_BLOCKS_VERT)
|
|
return 0
|
|
|
|
var/test = src.blockmap[B.gridy+1][new_x_position+1]
|
|
if(test)
|
|
return 0
|
|
|
|
//I guess we CAN move! Time to all move together!
|
|
for(var/datum/robustris_block/B in superblock)
|
|
B.gridx = B.gridx + magnitude
|
|
|
|
return 1
|
|
|
|
rotate_block(var/datum/robustris_block/theblock, x_adjust=1, y_adjust=-1)
|
|
if(!theblock || theblock.cannot_rotate || ( last_rotation && world.time < (last_rotation + SETUP_ROTATE_DELAY) ))
|
|
return 0
|
|
|
|
last_rotation = world.time
|
|
var/n = 0
|
|
var/list/new_posx = new /list(theblock.related.len)
|
|
var/list/new_posy = new /list(theblock.related.len)
|
|
|
|
//Determine and test new block location for collision.
|
|
for(var/datum/robustris_block/B in theblock.related)
|
|
n++
|
|
var/testx = theblock.gridx + (B.rely * x_adjust)
|
|
var/testy = theblock.gridy + (B.relx * y_adjust)
|
|
if(testx < 0 || testx >= SETUP_BLOCKS_HORIZ || testy < 0)
|
|
return 0
|
|
|
|
if(!isnull(src.blockmap[testy + 1][testx + 1]))
|
|
return 0
|
|
|
|
new_posx[n] = testx
|
|
new_posy[n] = testy
|
|
|
|
//If everything is OK then go ahead and move them.
|
|
n = 0
|
|
for(var/datum/robustris_block/B in theblock.related)
|
|
n++
|
|
B.gridx = new_posx[n]
|
|
B.relx = B.gridx - theblock.gridx
|
|
B.gridy = new_posy[n]
|
|
B.rely = B.gridy - theblock.gridy
|
|
|
|
return 1
|
|
|
|
check_completion(var/list/rows_to_shift = list())
|
|
for(var/iy in rows_to_shift)
|
|
for(var/ix=1,ix <= SETUP_BLOCKS_HORIZ, ix++)
|
|
var/datum/robustris_block/check = src.blockmap[iy+1][ix]
|
|
if(isnull(check))
|
|
rows_to_shift -= iy
|
|
break
|
|
|
|
if(rows_to_shift.len)
|
|
for(var/n in rows_to_shift)
|
|
src.blockmap.Cut(n+1,n+2)
|
|
src.blockmap += new /list(rows_to_shift.len, SETUP_BLOCKS_HORIZ)
|
|
|
|
for(var/datum/robustris_block/B in src.blocks)
|
|
if(B.gridy in rows_to_shift)
|
|
src.blocks -= B
|
|
qdel(B)
|
|
continue
|
|
else
|
|
var/shift_count = 0
|
|
for(var/n in rows_to_shift)
|
|
if(n < B.gridy)
|
|
shift_count++
|
|
|
|
B.gridy -= shift_count
|
|
|
|
src.highscore += (100 * rows_to_shift.len)
|
|
|
|
return
|
|
|
|
/datum/robustris_block
|
|
var/gridx = 0
|
|
var/gridy = 0
|
|
var/list/related = list()
|
|
var/cannot_rotate = 0 //Don't even bother trying!
|
|
var/relx = 0
|
|
var/rely = 0 //Coordinates relative to an origin block.
|
|
|
|
New(var/starting_x=0,var/starting_y=0,var/datum/robustris_block/origin)
|
|
..()
|
|
gridx = starting_x
|
|
gridy = starting_y
|
|
if(origin)
|
|
src.relx = src.gridx - origin.gridx
|
|
src.rely = src.gridy - origin.gridy
|
|
|
|
return
|
|
|
|
/datum/computer/file/pda_program/arcade
|
|
name = "Arcade 250"
|
|
size = 8
|
|
var/enemy_name = "Space Villian"
|
|
var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc
|
|
var/player_hp = 30 //Player health/attack points
|
|
var/player_mp = 10
|
|
var/enemy_hp = 45 //Enemy health/attack points
|
|
var/enemy_mp = 20
|
|
var/gameover = 0
|
|
var/blocked = 0 //Player cannot attack/heal while set
|
|
|
|
New(obj/holding as obj)
|
|
..()
|
|
|
|
var/name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Evil ", "the Dread King ", "the Space ", "Lord ")
|
|
var/name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon")
|
|
|
|
src.enemy_name = replacetext((name_part1 + name_part2), "the ", "")
|
|
|
|
|
|
|
|
return_text()
|
|
if(..())
|
|
return
|
|
|
|
var/dat = src.return_text_header()
|
|
|
|
dat += "<center><h4>[src.enemy_name]</h4></center>"
|
|
|
|
dat += "<br><center><h3>[src.temp]</h3></center>"
|
|
dat += "<br><center>Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]</center>"
|
|
|
|
if (src.gameover)
|
|
dat += "<center><b><a href='byond://?src=\ref[src];newgame=1'>New Game</a>"
|
|
else
|
|
dat += "<center><b><a href='byond://?src=\ref[src];attack=1'>Attack</a> | "
|
|
dat += "<a href='byond://?src=\ref[src];heal=1'>Heal</a> | "
|
|
dat += "<a href='byond://?src=\ref[src];charge=1'>Recharge Power</a>"
|
|
|
|
dat += "</b></center>"
|
|
|
|
return dat
|
|
|
|
Topic(href, href_list)
|
|
if(..())
|
|
return
|
|
|
|
if (!src.blocked)
|
|
if (href_list["attack"])
|
|
src.blocked = 1
|
|
var/attackamt = rand(2,6)
|
|
src.temp = "You attack for [attackamt] damage!"
|
|
src.master.updateSelfDialog()
|
|
|
|
sleep(10)
|
|
src.enemy_hp -= attackamt
|
|
src.arcade_action()
|
|
|
|
else if (href_list["heal"])
|
|
src.blocked = 1
|
|
var/pointamt = rand(1,3)
|
|
var/healamt = rand(6,8)
|
|
src.temp = "You use [pointamt] magic to heal for [healamt] damage!"
|
|
src.master.updateSelfDialog()
|
|
|
|
sleep(10)
|
|
src.player_mp -= pointamt
|
|
src.player_hp += healamt
|
|
src.blocked = 1
|
|
src.master.updateSelfDialog()
|
|
src.arcade_action()
|
|
|
|
else if (href_list["charge"])
|
|
src.blocked = 1
|
|
var/chargeamt = rand(4,7)
|
|
src.temp = "You regain [chargeamt] points"
|
|
src.player_mp += chargeamt
|
|
|
|
src.master.updateSelfDialog()
|
|
sleep(10)
|
|
src.arcade_action()
|
|
|
|
if (href_list["newgame"]) //Reset everything
|
|
temp = "New Round"
|
|
player_hp = 30
|
|
player_mp = 10
|
|
enemy_hp = 45
|
|
enemy_mp = 20
|
|
gameover = 0
|
|
|
|
src.master.add_fingerprint(usr)
|
|
src.master.updateSelfDialog()
|
|
return
|
|
|
|
proc/arcade_action()
|
|
if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0))
|
|
src.gameover = 1
|
|
src.temp = "[src.enemy_name] has fallen! Rejoice!"
|
|
|
|
else if ((src.enemy_mp <= 5) && (prob(70)))
|
|
var/stealamt = rand(2,3)
|
|
src.temp = "[src.enemy_name] steals [stealamt] of your power!"
|
|
src.player_mp -= stealamt
|
|
src.master.updateSelfDialog()
|
|
|
|
if (src.player_mp <= 0)
|
|
src.gameover = 1
|
|
sleep(10)
|
|
src.temp = "You have been drained! GAME OVER"
|
|
|
|
else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4))
|
|
src.temp = "[src.enemy_name] heals for 4 health!"
|
|
src.enemy_hp += 4
|
|
src.enemy_mp -= 4
|
|
|
|
else
|
|
var/attackamt = rand(3,6)
|
|
src.temp = "[src.enemy_name] attacks for [attackamt] damage!"
|
|
src.player_hp -= attackamt
|
|
|
|
if ((src.player_mp <= 0) || (src.player_hp <= 0))
|
|
src.gameover = 1
|
|
src.temp = "You have been crushed! GAME OVER"
|
|
|
|
src.blocked = 0
|
|
return
|
|
|
|
/datum/computer/file/pda_program/codebreaker
|
|
name = "CodeBreaker"
|
|
size = 4
|
|
var/solution = ""
|
|
var/code_length = 4
|
|
var/list/code_chars = list("A","B","C","D")
|
|
var/attempts = 10
|
|
var/init_attempts = 0
|
|
var/list/attempt_log = list()
|
|
var/playing = 0
|
|
var/temp = ""
|
|
var/difficulty = "Normal"
|
|
|
|
return_text()
|
|
if(..())
|
|
return
|
|
|
|
var/dat = src.return_text_header()
|
|
|
|
dat += "<center><h4>CodeBreaker</h4></center>"
|
|
|
|
if (playing)
|
|
dat += "<br>[src.temp]"
|
|
|
|
if(playing == -1)
|
|
dat += "<br><b>The Code was</b> \"[src.solution]\""
|
|
dat += "<br><a href='byond://?src=\ref[src];menu=1'>Main Menu</a>"
|
|
else
|
|
dat += "<br><a href='byond://?src=\ref[src];guess=1'>Guess</a>"
|
|
dat += "<br><a href='byond://?src=\ref[src];giveup=1'>Give Up</a>"
|
|
|
|
dat += "<br><small>Attempts Remaining: [src.attempts]"
|
|
for(var/i=0, i < src.attempt_log.len ,i++)
|
|
dat += "<br>[attempt_log[i+1]]"
|
|
dat += "</small><br>"
|
|
|
|
else
|
|
dat += "<br><center><h3><a href='byond://?src=\ref[src];newgame=1'>New Game</a></h3></center>"
|
|
dat += "<br><center><h3><a href='byond://?src=\ref[src];difficulty=1'>Difficulty: [src.difficulty]</a></h3></center>"
|
|
|
|
return dat
|
|
|
|
Topic(href, href_list)
|
|
if(..())
|
|
return
|
|
|
|
if (href_list["newgame"])
|
|
src.playing = 1
|
|
src.solution = ""
|
|
var/length = src.code_length
|
|
while (length > 0)
|
|
length--
|
|
src.solution += "[pick(code_chars)]"
|
|
switch(src.difficulty)
|
|
if("Easy") src.attempts = 3
|
|
if("Normal") src.attempts = 10
|
|
if("Hard") src.attempts = 30
|
|
if("Ultra-Hard") src.attempts = 50
|
|
src.init_attempts = src.attempts
|
|
|
|
var/charstring = ""
|
|
for(var/X in code_chars)
|
|
charstring += "[X] "
|
|
src.temp = "This game has a [src.code_length]-character code featuring the characters \"[charstring]\". Good luck."
|
|
|
|
else if (href_list["menu"])
|
|
src.playing = 0
|
|
src.attempt_log = list()
|
|
src.temp = ""
|
|
src.solution = ""
|
|
|
|
else if (href_list["giveup"])
|
|
if(alert("Are you sure you want to give up?","CodeBreaker","Yes","No") == "Yes")
|
|
src.attempts = 0
|
|
src.playing = -1
|
|
src.temp = "<b>YOU LOSE!</b>"
|
|
|
|
else if (href_list["guess"])
|
|
var/attempt = input("Enter your guess.","CodeBreaker") as null|text
|
|
if(!attempt)
|
|
src.temp = "Illegal move."
|
|
src.master.updateSelfDialog()
|
|
return
|
|
if(length(attempt) != length(src.solution))
|
|
src.temp = "Illegal move."
|
|
src.master.updateSelfDialog()
|
|
return
|
|
if (attempt == src.solution)
|
|
src.playing = -1
|
|
src.temp = "<b>YOU WIN!</b>"
|
|
else
|
|
if (src.attempts <= 1)
|
|
src.playing = -1
|
|
src.temp = "<b>YOU LOSE!</b>"
|
|
else
|
|
src.attempts--
|
|
|
|
var/length = length(src.solution)
|
|
|
|
var/list/lockcode_list = list()
|
|
for(var/i=0,i < length,i++)
|
|
//lockcode_list += "[copytext(bp.lockcode,i+1,i+2)]"
|
|
lockcode_list["[copytext(src.solution,i+1,i+2)]"]++
|
|
|
|
var/correct_full = 0
|
|
var/correct_char = 0
|
|
var/current
|
|
var/seek = 0
|
|
for(var/i=0,i < length,i++)
|
|
current = copytext(attempt,i+1,i+2)
|
|
if (current == copytext(src.solution,i+1,i+2))
|
|
correct_full++
|
|
//correct_char++
|
|
//continue
|
|
seek = lockcode_list.Find(current)
|
|
if (seek)
|
|
correct_char++
|
|
lockcode_list[current]--
|
|
if (lockcode_list[current] <= 0)
|
|
lockcode_list -= current
|
|
|
|
src.attempt_log.Insert(1,"Guess [src.init_attempts - src.attempts]: [attempt] ([correct_char]/[correct_full])")
|
|
src.temp = "Incorrect. [correct_char] correct characters, [correct_full] in correct position."
|
|
|
|
else if (href_list["difficulty"])
|
|
switch(src.difficulty)
|
|
if("Ultra-Hard")
|
|
src.set_difficulty("Easy",2,3)
|
|
src.code_chars = list("A","B")
|
|
if("Easy")
|
|
src.set_difficulty("Normal",4,10)
|
|
src.code_chars = list("A","B","C","D")
|
|
if("Normal")
|
|
src.set_difficulty("Hard",5,30)
|
|
src.code_chars = list("A","B","C","D","E")
|
|
if("Hard")
|
|
src.set_difficulty("Ultra-Hard",6,50)
|
|
src.code_chars = list("A","B","C","D","E","F")
|
|
|
|
src.master.add_fingerprint(usr)
|
|
src.master.updateSelfDialog()
|
|
return
|
|
|
|
proc/set_difficulty(var/diff,var/code_length,var/attempts)
|
|
if (!diff || !code_length || !attempts || !code_chars.len)
|
|
return null
|
|
src.difficulty = diff
|
|
src.code_length = code_length
|
|
src.attempts = attempts
|
|
|
|
#undef SETUP_BLOCKS_HORIZ
|
|
#undef SETUP_BLOCKS_VERT
|
|
#undef SETUP_BLOCK_COLOR
|
|
#undef SETUP_PLAYFIELD_COLOR
|
|
#undef SETUP_ROTATE_DELAY |