<commit_before>#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

from __future__ import print_function
import random
import re

# Local imports
import rollers
import generate

# Constants

# Keys into the subclass map, also usable for displaying categories, if
# desired.

KEY_ARMOR         = 'Armor/Shield'
KEY_WEAPON        = 'Weapon'
KEY_POTION        = 'Potion'
KEY_RING          = 'Ring'
KEY_ROD           = 'Rod'
KEY_SCROLL        = 'Scroll'
KEY_STAFF         = 'Staff'
KEY_WAND          = 'Wand'
KEY_WONDROUS_ITEM = 'Wondrous Item'

# Data file names
FILE_ITEMTYPES = 't_itemtypes'

# Tables
# Filled in on first use

TABLE_TYPES_LOADED = False
TABLE_TYPES_MINOR = []
TABLE_TYPES_MEDIUM = []
TABLE_TYPES_MAJOR = []

# Functions

def generate_generic(strength, roller, base_value):
    # Here, strength is merely 'minor', 'medium', 'major', so we need to
    # further qualify it with 'lesser' or 'greater'.
    
    # We don't want to use the roller mechanism, since this is not a table
    # choice, but rather an artifact of the new item system not having
    # provision for linkage with the settlement item generation system.

    # We may decide to change this later, but at least for now, the choice
    # between them will be 50/50.
    full_strength = random.choice(['lesser ', 'greater ']) + strength

    # Now, select an item type.
    roll = roller.roll('1d100')
    # This lookup only needs minor/medium/major.
    kind = get_item_type(strength, roll)

    return generate_specific_item(full_strength, kind, roller)


def generate_item(description, roller):
    # description is of the form: lesser/greater major/medium/minor <kind>
    parts = description.split(' ')
    strength = ' '.join(parts[0:2])
    kind = ' '.join(parts[2:])
    # Now we have the parts in a usable form.
    return generate_specific_item(strength, kind, roller)


def generate_specific_item(strength, kind, roller):
    # Create an object.
    item = create_item(kind)

    # Finish generating the item
    return item.generate(strength, roller)


def create_item(kind):
    # Create the apropriate Item subclass.
    subclass = ITEM_SUBCLASSES[kind]
    result = subclass.__new__(subclass)
    result.__init__()
    return result


def load_item_types(filename):
    global TABLE_TYPES_LOADED
    global TABLE_TYPES_MINOR
    global TABLE_TYPES_MEDIUM
    global TABLE_TYPES_MAJOR
    if TABLE_TYPES_LOADED:
        return
    f = open(filename, 'r')
    # Throw away the first and second lines, headers.
    # Eventually, we can read them in for metadata.
    f.readline()
    f.readline()
    # Now read the remaining lines.
    for line in f:
        data = line[:-1].split('\t')
        TABLE_TYPES_MINOR.append ({'type': data[0], 'range': data[1]})
        TABLE_TYPES_MEDIUM.append({'type': data[0], 'range': data[2]})
        TABLE_TYPES_MAJOR.append ({'type': data[0], 'range': data[3]})
    f.close()
    TABLE_TYPES_LOADED = True


def get_item_type(strength, roll):
    # Load Item Types
    load_item_types(FILE_ITEMTYPES)
    # Select the appropriate table.
    global TABLE_TYPES_MINOR
    global TABLE_TYPES_MEDIUM
    global TABLE_TYPES_MAJOR
    table = None
    if strength == 'minor':
        table = TABLE_TYPES_MINOR
    elif strength == 'medium':
        table = TABLE_TYPES_MEDIUM
    elif strength == 'major':
        table = TABLE_TYPES_MAJOR
    # Look for the roll among the mins and maxes.
    if table != None:
        for row in table:
            if in_range(roll, row['range']): return row['type']
    return ''


def split_range(range_str):
    span = (0,0)
    if '-' in range_str:
        span = tuple(range_str.split('-'))
    elif '–' in range_str:
        # Note: the character mentioned here is hex 2013, not a simple dash
        span = tuple(range_str.split('–'))
    elif '—' in range_str:
        # Note: the character mentioned here is hex 2014, not a simple dash
        span = tuple(range_str.split('—'))
    else:
        span = (range_str, range_str)
    return (int(span[0]), int(span[1]))


def in_range(roll, range_str):
    (rmin, rmax) = split_range(range_str)
    return roll >= rmin and roll <= rmax


def total_range(range_str):
    (rmin, rmax) = split_range(range_str)
    return rmax - rmin + 1


def parse_gold_price(price_str):
    match = re.match('\+(.*) gp', price_str)
    if match:
        return int(match.group(1).replace(',', ''))
    else:
        print('Error: cannot extract a price from', price_str)
    return 0


def parse_enhancement_price(price_str):
    match = re.match('\+(\d+) bonus', price_str)
    if match:
        return int(match.group(1))
    else:
        print('Error: cannot extract enhancement bonus from', price_str)
    return 0


#
# Classes
#


class TableRowMissingError(Exception):

    def __init__(self, message):
        # Base class init.
        Exception.__init__(self, message)


class Table(object):

    def __init__(self, filename):
        self.loaded = False
        self.metadata = []
        self.columns = []
        self.rows = []
        self.filename = filename


    def load(self):
        if self.loaded: return
        print('Table.load')
        # Open the file.
        f = open(self.filename, 'r')
        self.metadata = f.readline()[:-1].split('\t')
        self.columns = f.readline()[:-1].split('\t')
        col_roll = None
        col_count = len(self.columns)
        try:
            col_roll = self.columns.index('Roll')
        except ValueError:
            print('Error finding Roll column in table', self.filename)
            raise
        # Total up all the roll ranges
        total_rolls = 0
        row_number = 0
        # Read entries as tab-separated values.
        for line in f:
            if line.startswith('#'): continue
            row = line[:-1].split('\t')
            if len(row) < col_count:
                print('Error: row', row_number, 'does not have enough columns')
            total_rolls += total_range(row[col_roll])
            self.rows.append(row)<commit_msg>Removed a debug print.<commit_after>#!/usr/bin/env python
# vim: set fileencoding=utf-8 :

from __future__ import print_function
import random
import re

# Local imports
import rollers
import generate

# Constants

# Keys into the subclass map, also usable for displaying categories, if
# desired.

KEY_ARMOR         = 'Armor/Shield'
KEY_WEAPON        = 'Weapon'
KEY_POTION        = 'Potion'
KEY_RING          = 'Ring'
KEY_ROD           = 'Rod'
KEY_SCROLL        = 'Scroll'
KEY_STAFF         = 'Staff'
KEY_WAND          = 'Wand'
KEY_WONDROUS_ITEM = 'Wondrous Item'

# Data file names
FILE_ITEMTYPES = 't_itemtypes'

# Tables
# Filled in on first use

TABLE_TYPES_LOADED = False
TABLE_TYPES_MINOR = []
TABLE_TYPES_MEDIUM = []
TABLE_TYPES_MAJOR = []

# Functions

def generate_generic(strength, roller, base_value):
    # Here, strength is merely 'minor', 'medium', 'major', so we need to
    # further qualify it with 'lesser' or 'greater'.
    
    # We don't want to use the roller mechanism, since this is not a table
    # choice, but rather an artifact of the new item system not having
    # provision for linkage with the settlement item generation system.

    # We may decide to change this later, but at least for now, the choice
    # between them will be 50/50.
    full_strength = random.choice(['lesser ', 'greater ']) + strength

    # Now, select an item type.
    roll = roller.roll('1d100')
    # This lookup only needs minor/medium/major.
    kind = get_item_type(strength, roll)

    return generate_specific_item(full_strength, kind, roller)


def generate_item(description, roller):
    # description is of the form: lesser/greater major/medium/minor <kind>
    parts = description.split(' ')
    strength = ' '.join(parts[0:2])
    kind = ' '.join(parts[2:])
    # Now we have the parts in a usable form.
    return generate_specific_item(strength, kind, roller)


def generate_specific_item(strength, kind, roller):
    # Create an object.
    item = create_item(kind)

    # Finish generating the item
    return item.generate(strength, roller)


def create_item(kind):
    # Create the apropriate Item subclass.
    subclass = ITEM_SUBCLASSES[kind]
    result = subclass.__new__(subclass)
    result.__init__()
    return result


def load_item_types(filename):
    global TABLE_TYPES_LOADED
    global TABLE_TYPES_MINOR
    global TABLE_TYPES_MEDIUM
    global TABLE_TYPES_MAJOR
    if TABLE_TYPES_LOADED:
        return
    f = open(filename, 'r')
    # Throw away the first and second lines, headers.
    # Eventually, we can read them in for metadata.
    f.readline()
    f.readline()
    # Now read the remaining lines.
    for line in f:
        data = line[:-1].split('\t')
        TABLE_TYPES_MINOR.append ({'type': data[0], 'range': data[1]})
        TABLE_TYPES_MEDIUM.append({'type': data[0], 'range': data[2]})
        TABLE_TYPES_MAJOR.append ({'type': data[0], 'range': data[3]})
    f.close()
    TABLE_TYPES_LOADED = True


def get_item_type(strength, roll):
    # Load Item Types
    load_item_types(FILE_ITEMTYPES)
    # Select the appropriate table.
    global TABLE_TYPES_MINOR
    global TABLE_TYPES_MEDIUM
    global TABLE_TYPES_MAJOR
    table = None
    if strength == 'minor':
        table = TABLE_TYPES_MINOR
    elif strength == 'medium':
        table = TABLE_TYPES_MEDIUM
    elif strength == 'major':
        table = TABLE_TYPES_MAJOR
    # Look for the roll among the mins and maxes.
    if table != None:
        for row in table:
            if in_range(roll, row['range']): return row['type']
    return ''


def split_range(range_str):
    span = (0,0)
    if '-' in range_str:
        span = tuple(range_str.split('-'))
    elif '–' in range_str:
        # Note: the character mentioned here is hex 2013, not a simple dash
        span = tuple(range_str.split('–'))
    elif '—' in range_str:
        # Note: the character mentioned here is hex 2014, not a simple dash
        span = tuple(range_str.split('—'))
    else:
        span = (range_str, range_str)
    return (int(span[0]), int(span[1]))


def in_range(roll, range_str):
    (rmin, rmax) = split_range(range_str)
    return roll >= rmin and roll <= rmax


def total_range(range_str):
    (rmin, rmax) = split_range(range_str)
    return rmax - rmin + 1


def parse_gold_price(price_str):
    match = re.match('\+(.*) gp', price_str)
    if match:
        return int(match.group(1).replace(',', ''))
    else:
        print('Error: cannot extract a price from', price_str)
    return 0


def parse_enhancement_price(price_str):
    match = re.match('\+(\d+) bonus', price_str)
    if match:
        return int(match.group(1))
    else:
        print('Error: cannot extract enhancement bonus from', price_str)
    return 0


#
# Classes
#


class TableRowMissingError(Exception):

    def __init__(self, message):
        # Base class init.
        Exception.__init__(self, message)


class Table(object):

    def __init__(self, filename):
        self.loaded = False
        self.metadata = []
        self.columns = []
        self.rows = []
        self.filename = filename


    def load(self):
        if self.loaded: return
        # Open the file.
        f = open(self.filename, 'r')
        self.metadata = f.readline()[:-1].split('\t')
        self.columns = f.readline()[:-1].split('\t')
        col_roll = None
        col_count = len(self.columns)
        try:
            col_roll = self.columns.index('Roll')
        except ValueError:
            print('Error finding Roll column in table', self.filename)
            raise
        # Total up all the roll ranges
        total_rolls = 0
        row_number = 0
        # Read entries as tab-separated values.
        for line in f:
            if line.startswith('#'): continue
            row = line[:-1].split('\t')
            if len(row) < col_count:
                print('Error: row', row_number, 'does not have enough columns')
            total_rolls += total_range(row[col_roll])
            self.rows.append(row)
{'fraction_non_alphanumeric': 0.1086288514243003, 'fraction_numerical': 0.0068100656091686735, 'mean_word_length': 2.7040910489080283, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6006668', 'n_tokens_mistral': 3921, 'n_tokens_neox': 3791, 'n_words': 1109}