v50 Steam/Premium information for editors
  • v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
  • Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.

Difference between revisions of "User:Button/ModestMod"

From Dwarf Fortress Wiki
Jump to navigation Jump to search
(update)
Line 64: Line 64:
 
files = [] # dict string:list(string), where the first string is the raw file name, and the list is a list of  
 
files = [] # dict string:list(string), where the first string is the raw file name, and the list is a list of  
 
valid_tokens = [] # all the pipe-separated graphics tokens loaded into memory
 
valid_tokens = [] # all the pipe-separated graphics tokens loaded into memory
ascii_codes = [":"="###", "["="###", "]"="###", "'"="###"] # Gotta include the 0 for the tags-parsing routine - it expects 3 digits
+
ascii_codes = [":"="###", "["="###", "]"="###", "'"="###"] # Gotta include leading 0s for the tags-parsing routine - it expects 3 digits
  
 
# Process graphicsified raws into a dict, or load from the save of a previously generated dict
 
# Process graphicsified raws into a dict, or load from the save of a previously generated dict
 
def generate_graphics_dict(sourcedir, graphicsdict):
 
def generate_graphics_dict(sourcedir, graphicsdict):
 
for file in sourcedir:
 
for file in sourcedir:
currentobj = []
+
currentobj = [] # Stack of tuples. Holds all the milestone type:value pairs we've passed already. Keeps track of how deep we are.
passedstones = []
+
passedstones = [] # Stack. Holds all the milestone types we've passed already. Should be equivalent to the first value of each duple in currentobj.
 
for line in file:
 
for line in file:
for full_tag in tags(line):
+
for full_tag in tags(line): # For every tag in the file
tag = first_token(full_tag)
+
tag_type = first_token(full_tag)
if is_milestone(tag):
+
if is_milestone(tag_type): # If the tag is of a milestone type
if passedstones not contains tag:
+
if not passedstones.contains(tag_type): # If this isn't a milestone type we've already seen
passedstones.add(tag)
+
passedstones.push(tag_type)
currentobj[tag] = body_tokens(full_tag)
+
currentobj.push((tag_type,body_tokens(full_tag)))
else: #milestone is a new instance of a thing
+
else: #milestone is a new instance of a thing
while passedstones contains tag:
+
while passedstones.contains(tag_type): # Clearing out all the milestones until we no longer have a competing tag of type tag_type in the memory
rollback = passedstones.pop()
+
passedstones.pop()
currentobj.remove(rollback)
+
currentobj.pop()
passedstones.add(tag)
+
passedstones.push(tag_type) # Put the new tag on the stack
currentobj[tag] = body_tokens(full_tag)
+
currentobj.push((tag_type,body_tokens(full_tag)))
elif is_graphics_tag(currentobj,tag):
+
elif is_graphics_tag(currentobj,tag): # This assumes milestones can't be graphics tags, which is correct now but may be a problem later.
 
graphicsdict[graphics_tag(currentobj,tag)] = full_tag
 
graphicsdict[graphics_tag(currentobj,tag)] = full_tag
  
 
# Takes a line of raw file and returns all tags in the file. (Without the [brackets])
 
# Takes a line of raw file and returns all tags in the file. (Without the [brackets])
 
def tags(line):
 
def tags(line):
 +
processed_line = escape_problematic_literals(line)
 +
to_return = [] # list of strings, a la split()
 +
while processed_line.contains('[') and processed_line.contains(']') and processed_line.firstIndexOf('[') < processed_line.lastIndexOf(']'):
 +
if processed_line.firstIndexOf(']') < processed_line.firstIndexOf('['):
 +
processed_line = processed_line.substring(processed_line.firstIndexOf('['))
 +
to_return.append(processed_line.substring(processed_line.firstIndexOf('[')+1,processed_line.firstIndexOf(']')))
 +
processed_line = processed_line.substring(processed_line.firstIndexOf(']')+1)
 +
return to_return
 +
 +
def escape_problematic_literals(rawline):
 +
line = rawline.copy()
 
# Replace literal key characters with number codes
 
# Replace literal key characters with number codes
 
# Literal colons are going to require some special processing, because of the following case:  GROWTH:'r':'x': etc. That's why we can't just use a blind replaceAll.
 
# Literal colons are going to require some special processing, because of the following case:  GROWTH:'r':'x': etc. That's why we can't just use a blind replaceAll.
bracketscount = 0
+
bracketscount = 0 # If odd, we are inside a tag. If even, we are outside a tag.
count = 0
+
count = 0 # Where we are in the string
 
while count < line.length:
 
while count < line.length:
 +
# Going from inside a tag to outside or vice versa
 
if (bracketscount%2 == 0 and line[count] == "[") or (bracketscount%2 == 1 and line[count] == "]"):
 
if (bracketscount%2 == 0 and line[count] == "[") or (bracketscount%2 == 1 and line[count] == "]"):
 
bracketscount += 1
 
bracketscount += 1
 +
# We are inside a tag and we have discovered a ' character beginning a literal value, with another 2 characters down on the other side.
 
elif bracketscount%2 == 1 and line[count] == "'"  and line[count+2] == "'":
 
elif bracketscount%2 == 1 and line[count] == "'"  and line[count+2] == "'":
 +
# If the character could be a problem for later processing, replace it with its ascii code.
 
if line[count+1] in ascii_codes.keySet():
 
if line[count+1] in ascii_codes.keySet():
 
replace_char = line[count+1]
 
replace_char = line[count+1]
line[count] = ascii_codes[replace_char][0] # TODO: Doublecheck that this correctly replaces all 3 characters; see if there's a way that could be length-agnostic
+
line[count] = ascii_codes[replace_char][0] # TODO: see if there's a way this can be length-agnostic
 
line[count+1] = ascii_codes[replace_char][1]
 
line[count+1] = ascii_codes[replace_char][1]
 
line[count+2] = ascii_codes[replace_char][2]
 
line[count+2] = ascii_codes[replace_char][2]
Line 105: Line 119:
 
count += 1
 
count += 1
 
# line has now had its literal "use this tile" versions of its special characters replaced with their numbers.
 
# line has now had its literal "use this tile" versions of its special characters replaced with their numbers.
to_return = [] # list of strings, a la split()
+
return line
while line.contains('[') and line.contains(']') and line.firstIndexOf('[') < line.lastIndexOf(']'):
 
if line.firstIndexOf(']') < line.firstIndexOf('['):
 
line = line.substring(line.firstIndexOf('['))
 
to_return.append(line.substring(line.firstIndexOf('[')+1,line.firstIndexOf(']')))
 
line = line.substring(line.firstIndexOf(']')+1)
 
return to_return
 
 
 
 
def first_token(tag)
 
def first_token(tag)
return  
+
return tag.substring(0,tag.firstIndexOf(':')) # Assuming all literal ':'s have been replaced with their ascii codes
  
 
# Apply graphics dict to the raws found in sourcedir, outputting in tardir .
 
# Apply graphics dict to the raws found in sourcedir, outputting in tardir .
Line 122: Line 130:
 
passedstones = []
 
passedstones = []
 
currentobj = []
 
currentobj = []
create file in tardir, and open for write
+
# TODO create file in tardir, and open for write
 
for line in file:
 
for line in file:
moddedline = line
+
moddedline = escape_problematic_literals(line) # Our output
for full_tag in tags(line):
+
for full_tag in tags(line): # For every tag in the raw file we're applying the graphics to
tag = first_token(full_tag)
+
tag_type = first_token(full_tag)
if is_milestone(tag):
+
if is_milestone(tag_type): # Keep track of our milestone status
if passedstones not contains tag:
+
if not passedstones.contains(tag_type):
passedstones.add(tag)
+
passedstones.push(tag_type)
currentobj[tag] = body_tokens(full_tag)
+
currentobj.push((tag_type,body_tokens(full_tag)))
 
else:
 
else:
 
if has_remaining_graphics_tags(graphicsdictcopy,currentobj):
 
if has_remaining_graphics_tags(graphicsdictcopy,currentobj):
Line 136: Line 144:
 
moddedline += '\n'
 
moddedline += '\n'
 
moddedline += write_tag(graphicstag)
 
moddedline += write_tag(graphicstag)
graphicsdictcopy.remove(graphics_tag(currentobj,tag))
+
graphicsdictcopy.remove(graphics_tag(currentobj,full_tag))
while passedstones contains tag:
+
while passedstones.contains(tag_type):
rollback = passedstones.pop()
+
passedstones.pop()
currentobj.remove(rollback)
+
currentobj.pop()
passedstones.add(tag)
+
passedstones.add(full_tag)
 
currentobj[tag] = body_tokens(full_tag)
 
currentobj[tag] = body_tokens(full_tag)
elif is_graphics_tag(currentobj, tag):
+
elif is_graphics_tag(currentobj, full_tag):
moddedline.replace(full_tag, graphicsdictcopy[graphics_tag(currentobj,tag)])
+
# TODO handle graphics lines that aren't present in the graphics we're applying
graphicsdictcopy.remove(graphics_tag(currentobj,tag))
+
moddedline.replace(full_tag,get_replacement_tag(full_tag,graphicsdictcopy))
 +
graphicsdictcopy.remove(graphics_tag(currentobj,full_tag))
 +
# If it's not a milestone or a graphics tag, just write it as it appeared in the original file
 
tardir.write(moddedline + '\n')
 
tardir.write(moddedline + '\n')
 
close file
 
close file
Line 163: Line 173:
 
tarfile.write(rawformatted)
 
tarfile.write(rawformatted)
 
tarfile.close()
 
tarfile.close()
 +
 +
# Convenience method for if this tag is a milestone
 +
def is_milestone(tag_type):
 +
return milestones.contains(tag_type)
 +
 +
def body_tokens(full_tag):
 +
return full_tag.substring(full_tag.firstIndexOf(':'),length(full_tag))
 +
 
</pre>
 
</pre>
  

Revision as of 00:39, 19 April 2015

This is a directory page for my Modest Mod work.

I feel a little bad for clogging up the wiki with this stuff, but sometimes I get bored and I'm not at my home computer.

Plans

  • Moving the no-fear-of-commitment orientation mods out into a pair of creature variations, in c_variation_modest. May make a Module applying them to sapients as well. Eternal Lovers are kind of frustrating.
  • Could probably just make the plant growths that I currently have wrapping tree nuts, edible or pressable or whatever in their own right, and never have to deal with the seeds. OTOH, that might mess up grinding them to paste/pressing them? And would still need the hulling reaction for plantable legumes.
  • Could change implementation of all plants, including those brewed 'whole', into growths. Then would be able to share reactions better, and do seed/no seed on a purely FAKESEED basis.
    • Probably not worth it in vanilla, but maybe fore plant features, since we'll be needing to mill "whole plants" (e.g. cassava, whip vines) and also to mill seedheads.
  • Need to move Plump Helmets back to a usable plant instead of a fruit. Save it as fruit for the Basic Adventurer's Pack.
  • Need to look at the expanded creature variation replacement tokens in preparation for the vampire anti-sobriety module.

Accelerated

  • Need to look at the old Accelerated Modest Mod and see how much of it is applicable to the current version.
  • Need to see about thinning down plant materials, like a lot.
  • Need to remove useless plant growths, like cherry blossoms etc. Leaves? Or would that be too ugly?
  • Could probably reduce grass to a single species? Or would that make pandas shitty?

Plant Features

  • Could probably make grain use the fruit(like?) reactions for brewing, milling, etc.
  • Kahlua & Chajun & possibly the plant products that are used to make them could give a temporary [NOSLEEP] tag? Followed by a 'crash' of a drowsiness syndrome?
  • Jellies? Preserves? Juices?
  • More variation in material values

Basic Adventurer's Pack

  • Plump helmet to fruit
  • Enable a whole bunch of sapients playable as outsiders. Not just the ones in the gear-already-exists size range.
    • Hahaha, fairies as a playable outsider race |D That would be silly
  • Plant fiber thread. Rope reeds, pig tail stalks, others?
    • For the merge with Plant Features, abaca/banana/pineapple leaves, cotton bolls, etc. A lot of the plant fabric stuff is Plant Features-necessary.
  • Cooking. Just biscuits? Or full-on recipes?
    • Flour? Oil? Good use for mortar & pestle...
    • Maybe a balanced meal would require a veg, a protein, & a sugar/starch, & would provide minor (temporary) attribute boosts?
  • Remove liquid from bag without dumping out entire bag
  • Leather armor. Tanning if it doesn't already exist.
  • Backpacks, bags, quivers, waterskins.
  • Bone & shell armor.
  • Bone bows, crossbows, blowguns, & ammo.
    • Arrow bamboo?
  • Self-buff "cheats"?
  • Cloth products?
    • Haircloth?
    • Maybe just enable as material for backpacks etc. Don't want to overload with options, menu is kind of crap.
  • Trophy jewelry

Raws

Some related LNP pseudocode


graphicsdict = []		# dict string:string, where the first string is the tag type formatted with pipes a la that section up there (but with $'s replaced), and the second string is the tag as it appears in the raws
milestones=["OBJECT","CREATURE","CASTE","PLANT","GROWTH","INORGANIC","BUILDING_WORKSHOP","BUILDING_FURNACE","ENTITY","ITEM_TOOL"]
files = []			# dict string:list(string), where the first string is the raw file name, and the list is a list of 
valid_tokens = []		# all the pipe-separated graphics tokens loaded into memory
ascii_codes = [":"="###", "["="###", "]"="###", "'"="###"]			# Gotta include leading 0s for the tags-parsing routine - it expects 3 digits

# Process graphicsified raws into a dict, or load from the save of a previously generated dict
def generate_graphics_dict(sourcedir, graphicsdict):
	for file in sourcedir:
		currentobj = []							# Stack of tuples. Holds all the milestone type:value pairs we've passed already. Keeps track of how deep we are.
		passedstones = []						# Stack. Holds all the milestone types we've passed already. Should be equivalent to the first value of each duple in currentobj.
		for line in file:
			for full_tag in tags(line):				# For every tag in the file
				tag_type = first_token(full_tag)
				if is_milestone(tag_type):				# If the tag is of a milestone type
					if not passedstones.contains(tag_type):	# If this isn't a milestone type we've already seen
						passedstones.push(tag_type)
						currentobj.push((tag_type,body_tokens(full_tag)))
					else:								#milestone is a new instance of a thing
						while passedstones.contains(tag_type):	# Clearing out all the milestones until we no longer have a competing tag of type tag_type in the memory
							passedstones.pop()
							currentobj.pop()
						passedstones.push(tag_type)			# Put the new tag on the stack
						currentobj.push((tag_type,body_tokens(full_tag)))
				elif is_graphics_tag(currentobj,tag):		# This assumes milestones can't be graphics tags, which is correct now but may be a problem later.
					graphicsdict[graphics_tag(currentobj,tag)] = full_tag

# Takes a line of raw file and returns all tags in the file. (Without the [brackets])
def tags(line):
	processed_line = escape_problematic_literals(line)
	to_return = []		# list of strings, a la split()
	while processed_line.contains('[') and processed_line.contains(']') and processed_line.firstIndexOf('[') < processed_line.lastIndexOf(']'):
		if processed_line.firstIndexOf(']') < processed_line.firstIndexOf('['):
			processed_line = processed_line.substring(processed_line.firstIndexOf('['))
		to_return.append(processed_line.substring(processed_line.firstIndexOf('[')+1,processed_line.firstIndexOf(']')))
		processed_line = processed_line.substring(processed_line.firstIndexOf(']')+1)
	return to_return
	
def escape_problematic_literals(rawline):
	line = rawline.copy()
	# Replace literal key characters with number codes
	# Literal colons are going to require some special processing, because of the following case:  GROWTH:'r':'x': etc. That's why we can't just use a blind replaceAll.
	bracketscount = 0		# If odd, we are inside a tag. If even, we are outside a tag.
	count = 0				# Where we are in the string
	while count < line.length:
		# Going from inside a tag to outside or vice versa
		if (bracketscount%2 == 0 and line[count] == "[") or (bracketscount%2 == 1 and line[count] == "]"):
			bracketscount += 1
		# We are inside a tag and we have discovered a ' character beginning a literal value, with another 2 characters down on the other side.
		elif bracketscount%2 == 1 and line[count] == "'"  and line[count+2] == "'":
			# If the character could be a problem for later processing, replace it with its ascii code.
			if line[count+1] in ascii_codes.keySet():
				replace_char = line[count+1]
				line[count] = ascii_codes[replace_char][0]		# TODO: see if there's a way this can be length-agnostic
				line[count+1] = ascii_codes[replace_char][1]
				line[count+2] = ascii_codes[replace_char][2]
			count += 2
		count += 1	
	# line has now had its literal "use this tile" versions of its special characters replaced with their numbers.
	return line
	
def first_token(tag)
	return tag.substring(0,tag.firstIndexOf(':'))		# Assuming all literal ':'s have been replaced with their ascii codes

# Apply graphics dict to the raws found in sourcedir, outputting in tardir .
def apply_graphics(sourcedir, tardir, graphicsdict):
	graphicsdictcopy = graphicsdict.copy()		# This copies the object references of the dict item, not the reference to the dict nor the contents of the contents.
	for file in sourcedir:
		passedstones = []
		currentobj = []
		# TODO create file in tardir, and open for write
		for line in file:
			moddedline = escape_problematic_literals(line)							# Our output
			for full_tag in tags(line):					# For every tag in the raw file we're applying the graphics to
				tag_type = first_token(full_tag)
				if is_milestone(tag_type):				# Keep track of our milestone status
					if not passedstones.contains(tag_type):
						passedstones.push(tag_type)
						currentobj.push((tag_type,body_tokens(full_tag)))
					else:
						if has_remaining_graphics_tags(graphicsdictcopy,currentobj):
							for graphicstag in pull_remaining_graphics_tags(graphicsdictcopy,currentobj):
								moddedline += '\n'
								moddedline += write_tag(graphicstag)
								graphicsdictcopy.remove(graphics_tag(currentobj,full_tag))
						while passedstones.contains(tag_type):
							passedstones.pop()
							currentobj.pop()
						passedstones.add(full_tag)
						currentobj[tag] = body_tokens(full_tag)
				elif is_graphics_tag(currentobj, full_tag):
					# TODO handle graphics lines that aren't present in the graphics we're applying
					moddedline.replace(full_tag,get_replacement_tag(full_tag,graphicsdictcopy))
					graphicsdictcopy.remove(graphics_tag(currentobj,full_tag))
				# If it's not a milestone or a graphics tag, just write it as it appeared in the original file
			tardir.write(moddedline + '\n')
		close file

# Load valid graphics token definitions from file
def load_valid_graphics_tokens():
	filelocation = ..\blahblahblah\graphicstiles.txt
	for line in filelocation.open():
		if length(line.strip()) > 0:
			valid_tokens.append(line)
	filelocation.close()
		
# Write graphics dict to file
def save_graphics_dict(tarfile, graphicsdict):
	graphicsdictcopy = graphicsdict.copy()
	tarfile.open(write)
	for rawformmated in to_raw_format(graphicsdictcopy):
		tarfile.write(rawformatted)
	tarfile.close()
	
# Convenience method for if this tag is a milestone
def is_milestone(tag_type):
	return milestones.contains(tag_type)
	
def body_tokens(full_tag):
	return full_tag.substring(full_tag.firstIndexOf(':'),length(full_tag))

More well-formatted graphics token reference file

OBJECT:CREATURE|CREATURE:$|CREATURE_TILE:_
OBJECT:CREATURE|CREATURE:$|COLOR:_:_:_
OBJECT:CREATURE|CREATURE:$|GLOWTILE:_
OBJECT:CREATURE|CREATURE:$|GLOWCOLOR:_:_:_
OBJECT:CREATURE|CREATURE:$|ALTTILE:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_ALTTILE:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_COLOR:_:_:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_GLOWCOLOR:_:_:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_GLOWTILE:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_SOLDIER_ALTTILE:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_SOLDIER_TILE:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|CASTE_TILE:_
OBJECT:CREATURE|CREATURE:$|CREATURE_SOLDIER_TILE:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|REMAINS_COLOR:_:_:_
OBJECT:CREATURE|CREATURE:$|REMAINS_COLOR:_:_:_
OBJECT:CREATURE|CREATURE:$|SENSE_CREATURE_CLASS:$:_:_:_:_
OBJECT:CREATURE|CREATURE:$|CASTE:$|SENSE_CREATURE_CLASS:$:_:_:_:_
OBJECT:CREATURE|CREATURE:$|SOLDIER_ALTTILE:_

OBJECT:PLANT|PLANT:$|GROWTH|GROWTH_PRINT:_:_:_:_:_:$
OBJECT:PLANT|PLANT:$|TREE_TILE:_
OBJECT:PLANT|PLANT:$|DEAD_TREE_TILE:_
OBJECT:PLANT|PLANT:$|SAPLING_TILE:_
OBJECT:PLANT|PLANT:$|DEAD_SAPLING_TILE:_
OBJECT:PLANT|PLANT:$|TREE_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|DEAD_TREE_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|SAPLING_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|DEAD_SAPLING_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|PICKED_TILE:_
OBJECT:PLANT|PLANT:$|DEAD_PICKED_TILE:_
OBJECT:PLANT|PLANT:$|SHRUB_TILE:_
OBJECT:PLANT|PLANT:$|DEAD_SHRUB_TILE:_
OBJECT:PLANT|PLANT:$|PICKED_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|DEAD_PICKED_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|SHRUB_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|DEAD_SHRUB_COLOR:_:_:_
OBJECT:PLANT|PLANT:$|GRASS_TILES:_:_:_:_
OBJECT:PLANT|PLANT:$|ALT_GRASS_TILES:_:_:_:_
OBJECT:PLANT|PLANT:$|GRASS_COLORS:_:_:_:_:_:_:_:_:_:_:_:_
OBJECT:PLANT|PLANT:$|ALT_PERIOD:_:_
OBJECT:PLANT|PLANT:$|SEED:$:$:_:_:_

MATERIAL?:$|POWDER_DYE:_:_:_
MATERIAL?:$|TILE:_
MATERIAL?:$|ITEM_SYMBOL:_
MATERIAL?:$|DISPLAY_COLOR:_:_:_
MATERIAL?:$|BUILD_COLOR:_:_:_
MATERIAL?:$|TILE_COLOR:_:_:_
MATERIAL?:$|BASIC_COLOR:_:_:_
MATERIAL?:$|STATE_COLOR:_:_:_

INORGANIC:$|DISPLAY_COLOR:_:_:_
INORGANIC:$|TILE:_
INORGANIC:$|ITEM_SYMBOL:_

OBJECT:BUILDING_WORKSHOP|BUILDING_WORKSHOP:$|NAME_COLOR:_:_:_
OBJECT:BUILDING_WORKSHOP|BUILDING_WORKSHOP:$|TILE:$:$:_
OBJECT:BUILDING_FURNACE|BUILDING_FURNACE:$|TILE:$:$:_
OBJECT:BUILDING_WORKSHOP|BUILDING_WORKSHOP:$|COLOR:$:$:_:_:_
OBJECT:BUILDING_FURNACE|BUILDING_FURNACE:$|COLOR:$:$:_:_:_

OBJECT:ENTITY|ENTITY:$|COLOR:_:_:_

OBJECT:ITEM_TOOL?|ITEM_TOOL:$|TILE:_