code:
<?php $theme->display ( 'header' ); ?>

			<?php foreach ( $posts as $post ) { ?>
				<div id="post-<?php echo $post->id; ?>" class="<?php echo $post->statusname; ?>">

<a href="<?php echo $post->permalink; ?>" title="<?php echo $post->title; ?>"><?php echo $post->title_out; ?>

<?php echo $post->pubdate_out; ?>

						<?php echo $post->content_out; ?>

						<?php if ( is_array( $post->tags ) ) { ?>

<?php _e('Tagged:'); ?> <?php echo $post->tags_out; ?>

						<?php } ?>

<?php $theme->comments_link($post,'%d Comments','%d Comment','%d Comments'); ?>

					<?php if ( $loggedin ) { ?>
					<a href="<?php echo $post->editlink; ?>" title="<?php _e('Edit post'); ?>"><?php _e('Edit'); ?>
					<?php } ?>

			<?php } ?>

				<?php $theme->prev_page_link('« ' . _t('Newer Posts')); ?> <?php $theme->page_selector( null, array( 'leftSide' => 2, 'rightSide' => 2 ) ); ?> <?php $theme->next_page_link('» ' . _t('Older Posts')); ?>

		<?php $theme->display('sidebar'); ?>

	<?php $theme->display ( 'footer' ); ?>


code:
<?php $theme->display ( 'header' ); ?>

			<?php include 'loginform.php'; ?>

		<?php $theme->display ( 'sidebar' ); ?>

	<?php $theme->display ( 'footer' ); ?>

repo_name: DaSourcerer/habari


code:
<?php
if ( isset( $error ) ) {
?>

<?php _e('That login is incorrect.'); ?>

<?php
}
if ( $loggedin ) {
?>

<?php _e('You are logged in as'); ?> <?php echo $user->username; ?>.

<?php _e('Want to'); ?> <a href="<?php Site::out_url( 'habari' ); ?>/auth/logout"><?php _e('log out'); ?>?

<?php
}
else {
?>
<?php Plugins::act( 'theme_loginform_before' ); ?>
<form method="post" action="<?php URL::out( 'auth', array( 'page' => 'login' ) ); ?>">

		<?php _e('Name:'); ?>
		<input type="text" size="25" name="habari_username" id="habari_username">

		<?php _e('Password:'); ?>
		<input type="password" size="25" name="habari_password" id="habari_password">

	<?php Plugins::act( 'theme_loginform_controls' ); ?>

		<input type="submit" value="<?php _e('GO!'); ?>">

		<input class="submit" type="submit" name="submit_button" value="<?php _e('Reset password'); ?>">

</form>
<?php Plugins::act( 'theme_loginform_after' ); ?>
<?php
}
?>


code:
<?php $theme->display ( 'header' ); ?>

				<div id="post-<?php echo $post->id; ?>" class="<?php echo $post->statusname; ?>">

<a href="<?php echo $post->permalink; ?>" title="<?php echo $post->title; ?>"><?php echo $post->title_out; ?>

						<?php echo $post->content_out; ?>

						<?php if ( $loggedin ) { ?>
						<a href="<?php echo $post->editlink; ?>" title="<?php _e('Edit post'); ?>"><?php _e('Edit'); ?>
						<?php } ?>

		<?php $theme->display ( 'sidebar' ); ?>

	<?php $theme->display ( 'footer' ); ?>


code:
<?php $theme->display ( 'header' ); ?>

<?php _e('Results for search of'); ?> "<?php echo Utils::htmlspecialchars( $criteria ); ?>"

			<?php if (isset($post)) : ?>
<?php foreach ( $posts as $post ): ?>
				<div id="post-<?php echo $post->id; ?>" class="<?php echo $post->statusname; ?>">

<a href="<?php echo $post->permalink; ?>" title="<?php echo $post->title; ?>"><?php echo $post->title_out; ?>

					<?php $post->pubdate->out('F j, Y'); ?> -	<?php echo $post->content_excerpt; ?>

						<?php if ( is_array( $post->tags ) ) { ?>

<?php _e('Tagged:'); ?> <?php echo $post->tags_out; ?>

						<?php } ?>

<?php $theme->comments_link($post,'%d Comments','%d Comment','%d Comments'); ?>

					<?php if ( $loggedin ) { ?>
					<a href="<?php echo $post->editlink; ?>" title="<?php _e('Edit post'); ?>"><?php _e('Edit'); ?>
					<?php } ?>

<?php endforeach; ?>

				<?php $theme->prev_page_link('« ' . _t('Newer Results')); ?> <?php $theme->page_selector( null, array( 'leftSide' => 2, 'rightSide' => 2 ) ); ?> <?php $theme->next_page_link('» ' . _t('Older Results')); ?>
			<?php else: ?>

<?php _e('No results for'); ?> <?php echo Utils::htmlspecialchars( $criteria ); ?>

			<?php endif; ?>

		<?php $theme->display ( 'sidebar' ); ?>

	<?php $theme->display ( 'footer' ); ?>


code:
<?php Plugins::act( 'theme_searchform_before' ); ?>
     <form method="get" id="searchform" action="<?php URL::out('display_search'); ?>">

<input type="text" id="s" name="criteria" value="<?php if ( isset( $criteria ) ) { echo htmlentities($criteria, ENT_COMPAT, 'UTF-8'); } else { _e('Search'); } ?>">
 <input type="submit" id="searchsubmit" value="<?php _e('Go!'); ?>">

     </form>
<?php Plugins::act( 'theme_searchform_after' ); ?>


code:
		<?php $theme->display ( 'searchform' ); ?>

<a id="rss" href="<?php $theme->feed_alternate(); ?>" class="block"><?php _e('Subscribe to Feed'); ?>

<?php _e('Navigation'); ?>

<a href="<?php Site::out_url( 'habari' ); ?>"><?php _e('Home'); ?>

		<?php
		// List Pages
		foreach ( $pages as $page ) {
			echo '
permalink . '" title="' . $page->title . '">' . $page->title . '
' . "\n";
		}
		?>

<?php _e('Asides'); ?>

		<?php
	          foreach($asides as $post):
              echo '
';
              echo $post->pubdate->out('F j, Y') . ' - ' . '';
              echo 'permalink .'">' . $post->title_out . ''. $post->content_out;
              echo '
';

 		?>
	<?php endforeach; ?>

<?php _e('More Posts'); ?>

			<?php foreach($more_posts as $post): ?>
				<?php
				echo '
';
				echo 'permalink .'">' . $post->title_out . '';
				echo '
';
				?>
			<?php endforeach; ?>

<?php _e('Recent Comments'); ?>

	<?php foreach($recent_comments as $comment): ?>

<a href="<?php echo $comment->url ?>"><?php echo $comment->name ?> <?php _e('on'); ?> <a href="<?php echo $comment->post->permalink; ?>"><?php echo $comment->post->title; ?>

	<?php endforeach; ?>

<?php _e('User Login'); ?>

	<?php $theme->display ( 'loginform' ); ?>


code:
/* =General
-----------------------------------------------------------------------------*/

blockquote {
	border-left: 10px solid #41670F;
	padding: 5px 0 5px 20px;
	margin: 10px 0 10px 40px;
}

blockquote p {
	border-top: 1px solid #666;
	border-bottom: 1px solid #666;
	padding: 8px 0;
	font-style: italic;
}

.right {
	float: right;
}

.left {
	float: left;
}

img.right {
	border: 1px solid #666;
	padding: 3px;
	margin-left: 8px;
}

img.left {
	border: 1px solid #666;
	padding: 3px;
	margin-right: 8px;
}

/* Class for clearing floats */

.clear {
	clear: both;
}

/* define inline elements as block */

.block {
	display: block;
}

/* Remove border around linked images */

img {
	border: 0;
}

/* =Typography
-----------------------------------------------------------------------------*/

body {
	font: 108% "Lucida Grande", Lucida, Verdana, sans-serif;
	color: #666;
	background: #EEEEEE;
}

/* =Structure
-----------------------------------------------------------------------------*/

#wrapper {
	margin: 0 auto;
	background: #fff;
}

#masthead {
	margin: 20px 0 40px 0;
	border-bottom: 2px dashed #41670F;
	padding-bottom: 5px;
}

#content {
	text-align: left;
}

#primaryContent {
	margin-bottom: 10px;
}

#secondaryContent {

}

#footer {
	height: 60px;
	border-top: 2px dotted #41670F;
	padding-top: 5px;
	margin-top: 5px;
}

/* =Headings
-----------------------------------------------------------------------------*/

h1 {
	font-size: 225%;
	font-family: Georgia, "Times New Roman", Times, serif;
	color: #545454;
}

h2 {
	color: #545454;
	font-family: Trebuchet, Tahoma, Arial, sans-serif;
}

h3 {
	font-size: 123.1%;
	font-family: Georgia, "Times New Roman", Times, serif;
}

#masthead #branding h3 {
	font-style: italic;
	font-size: 125%;
}

#primaryContent h2 {
	font-size: 159%;
}

#page #content #primaryContent h2 {
	text-align: center;
	margin: 0;
}

#secondaryContent h2 {
	font-size: 144%;
}

#site {

}

#rss {

}

#aside {

}

#commentheading {

}

/* =Links
-----------------------------------------------------------------------------*/

a:link {
	color: #41670F;
}

a:visited {
	color: #41670F;
	text-decoration: none;
}

a:hover {
	text-decoration: none;
	color: #A37941;
}

a:active {
	color: #41670F;
}

ul#nav li a:link, ul#nav li a:visited {
	display: block;
	width: 200px;
	padding-bottom: 5px;
	color: #666;
	text-decoration: none;
	text-indent: 20px;
}

ul#nav li a:hover {
	color: #000;
}

#branding a {
	border: none;
}

ul#tidbits a {
	text-decoration: none;
}

/* =Masthead
-----------------------------------------------------------------------------*/

#branding {
}

/* =Main Nav
-----------------------------------------------------------------------------*/

/* =Primary Content
-----------------------------------------------------------------------------*/

#post-nav {
	margin: 10px 5px 40px 5px;
}

.cal {
	height: 76px;
	width: 70px;
	float: left;
	margin: 0  12px 7px 0;
	text-align: center;
	border: 1px solid #A37941;
}

.calyear {
	background: #A37941;
	color: #fff;
	padding: 0 13px;
}

.calday {
	font-size: 138.5%;
	margin: 0;
	padding: 0;
	text-align: center;
	color: #A37941;
}

.calmonth {
	font-size: 77%;
	margin: 0;
	border-top: 1px solid #A37941;
	color: #A37941;
	width: 100%;
}

.entry {
	font-family: Trebuchet, "Lucida Sans Unicode", "Lucida Grande", "Lucida Sans", Arial, sans-serif;
}

.draft {
	background: #FFF6BF;
	color: #514721;
	border-color: #FFD324;
	padding: 5px;
}

.entry ul {
	list-style-type: square;
	padding-left: 80px;
}

.entry li {
	padding-bottom: 4px;
}

.entryMeta {
	margin: 40px 5px 45px 5px;
	font-size: 92%;
}

.commentCount {
	float: right;
}

#pagenav {
	text-align: center;
	border: 1px solid #ccc;
	padding: 4px;
	background: #F5F5F5;
	margin-top: 10px;
}

#pagenav a {
	text-decoration: none;
	padding: 2px;
}

#pagenav a:hover {
	background: #545454;
	padding: 2px;
	color: #fff;
	text-decoration: none;
}

#pagenav a.current-page {
	border: 1px solid #545454;
	color: #545454;
	padding: 2px;
}

#content img {
        max-width: 100%;
}

/* =Secondary Content
-----------------------------------------------------------------------------*/

ul#nav {
	list-style-type: none;
}

ul#nav li {
	margin-bottom: 7px;
}

ul#asides {
	list-style-type: none;
	margin-left: 5px;
}

ul#moreposts {
	list-style-type: none;
	margin-left: 5px;
}

ul#moreposts li {
	padding-bottom: 5px;
}

ul#recentcomments {
	list-style-type: none;
	margin-left: 5px;
}

ul#recentcomments li {
	margin-bottom: 8px;
	list-style-type: none;
}

/* =Footer
-----------------------------------------------------------------------------*/

#footer p {
	text-align: center;
}

/* =Forms
-----------------------------------------------------------------------------*/

/* Removes fieldset borders. even on Opea 7 */

fieldset {
	border: 1px solid transparent;
}

/* =Tables
-----------------------------------------------------------------------------*/

table {
	border-spacing: 0;
	border-collapse: collapse;
}

td {
	text-align: left;
	font-weight: normal;
}

/*Comments-----------------------------------------------------------------------------*/

#comments {
	padding-top: 20px;
}

#pings {
	margin: 15px 0 25px 0;
}

.ping-meta {
	background: #ddd;
	border: 1px solid #ccc;
	padding: 4px;
	margin-bottom: 15px;
}

ul#pings-list {
	list-style-type: none;
}

ul#commentlist {
	list-style-type: none;
}

.comment {
	margin-bottom: 15px;
}

.comment-content {
	border: 1px solid #ccc;
	padding: 4px;
	background: #F5F5F5;
}

.comment-unapproved .comment-content {
	background: #ffc;
}

.comment-meta {
	background: #ddd;
	border: 1px solid #ccc;
	padding: 4px;
}

/* Comment Form - heavily leaned on code from Andy Budd's book CSS Mastery, re-used with permission from author */

/* fieldset styling */

#comment_form {
	padding-top: 25px;
}

fieldset {
	margin: 1em 0;

/*  space out the fieldsets a little*/
	padding: 1em;
	border: 1px solid #ccc;
	background-color: #F5F5F5
}

/* legend styling */

legend {
	font-weight: bold;
}

form div {
	position: relative;
	width: 100%;
	margin-bottom: 20px; /* not sure if this is really the place to do this. */
}

/* style for  labels */

label {
	float: left;
	width: 10em;
}

input[type="text"] {
	width: 200px;
}

input[type="text"], textarea {
	border-top: 2px solid #999;
	border-left: 2px solid #999;
	border-bottom: 1px solid #ccc;
	border-right: 1px solid #ccc;
}

input#submit {
	width: auto;
}

label .required {
	position: absolute;
	margin-left: 11em;
	left: 200px;
	right: 0;
	font-size: small;
	font-style: italic;
	color: #760000;
	padding-left: 35px;
}

/* style form elements on focus */

input:focus, textarea:focus {
	background: #ffc;
}

textarea {
	width: 350px;
	height: 200px;
}

/*Search Form*/

#searchsubmit {
	margin: 5px auto;
	width: 160px;
}

#s {
	height: 1.6em;
	padding: 3px;
	font-size: 100%;
}


code:
<?php $theme->display ( 'header' ); ?>

<?php _e('Posts Tagged with'); ?> <?php echo $theme->tag; ?>

			<?php foreach ( $posts as $post ) { ?>
				<div id="post-<?php echo $post->id; ?>" class="<?php echo $post->statusname; ?>">

<a href="<?php echo $post->permalink; ?>" title="<?php echo $post->title; ?>"><?php echo $post->title_out; ?>

					<?php echo $post->pubdate->out('F j, Y'); ?> -	<?php echo $post->content_excerpt; ?>

						<?php if ( is_array( $post->tags ) ) { ?>

<?php _e('Tagged:'); ?> <?php echo $post->tags_out; ?>

						<?php } ?>

<?php $theme->comments_link($post,'%d Comments','%d Comment','%d Comments'); ?>

					<?php if ( $loggedin ) { ?>
					<a href="<?php echo $post->editlink; ?>" title="<?php _e('Edit post'); ?>"><?php _e('Edit'); ?>
					<?php } ?>

			<?php } ?>

				<?php $theme->prev_page_link('« ' . _t('Newer Results')); ?> <?php $theme->page_selector( null, array( 'leftSide' => 2, 'rightSide' => 2 ) ); ?> <?php $theme->next_page_link('» ' . _t('Older Results')); ?>

		<?php $theme->display ( 'sidebar' ); ?>

	<?php $theme->display ( 'footer' ); ?>


code:
<?php

/**
 * CornerStone is a custom Theme class for the mzingi theme.
 *
 * @package Habari
 */

/**
 * @todo This stuff needs to move into the custom theme class:
 */

// We must tell Habari to use MyTheme as the custom theme class:
define( 'THEME_CLASS', 'CornerStone' );

/**
 * A custom theme for mzingi output
 */
class CornerStone extends Theme
{

	public function action_init_theme()
	{
		// Apply Format::autop() to comment content...
		Format::apply( 'autop', 'comment_content_out' );
		// Apply Format::tag_and_list() to post tags...
		Format::apply( 'tag_and_list', 'post_tags_out' );
		// Only uses the  tag, with the 'more' as the link to full post
		Format::apply_with_hook_params( 'more', 'post_content_out', 'more' );
		// Creates an excerpt option. echo $post->content_excerpt;
		Format::apply( 'autop', 'post_content_excerpt' );
		Format::apply_with_hook_params( 'more', 'post_content_excerpt', 'more',60, 1 );
		// Format the calendar like date for home, entry.single and entry.multiple templates
		Format::apply( 'format_date', 'post_pubdate_out','{Y}
{j}
{F}' );
	}

	/**
	 * Add additional template variables to the template output.
	 *
	 *  You can assign additional output values in the template here, instead of
	 *  having the PHP execute directly in the template.  The advantage is that
	 *  you would easily be able to switch between template types (RawPHP/Smarty)
	 *  without having to port code from one to the other.
	 *
	 *  You could use this area to provide "recent comments" data to the template,
	 *  for instance.
	 *
	 *  Note that the variables added here should possibly *always* be added,
	 *  especially 'user'.
	 *
	 *  Also, this function gets executed *after* regular data is assigned to the
	 *  template.  So the values here, unless checked, will overwrite any existing
	 *  values.
	 */
	public function add_template_vars()
	{
		if( !$this->template_engine->assigned( 'pages' ) ) {
			$this->assign('pages', Posts::get( array( 'content_type' => 'page', 'status' => Post::status('published') ) ) );
		}
		//For Asides loop in sidebar.php
		$this->assign( 'asides', Posts::get( array( 'tag'=>'aside', 'limit'=>5) ) );

		//for recent comments loop in sidebar.php
		$this->assign('recent_comments', Comments::get( array('limit'=>5, 'status'=>Comment::STATUS_APPROVED, 'orderby'=>'date DESC' ) ) );

		parent::add_template_vars();
		//visiting page/2, /3 will offset to the next page of posts in the sidebar
		$page =Controller::get_var( 'page' );
		$pagination =Options::get('pagination');
		if ( $page == '' ) { $page = 1; }
		$this->assign( 'more_posts', Posts::get(array ( 'status' => 'published','content_type' => 'entry', 'offset' => ($pagination)*($page), 'limit' => 5,  ) ) );

	}

	public function act_display_home( $user_filters = array() )
	{
		//To exclude aside tag from main content loop
	    parent::act_display_home( array( 'not:tag' => 'aside' ) );
	}

	/**
	 * Customize comment form layout with fieldsets. Needs thorough commenting.
	 */
	public function action_form_comment( $form ) {
		$form->append( 'fieldset', 'cf_commenterinfo', _t( 'About You' ) );
		$form->move_before( $form->cf_commenterinfo, $form->cf_commenter );

		$form->cf_commenter->move_into($form->cf_commenterinfo);
		$form->cf_commenter->caption = _t('Name:') . '' . ( Options::get('comments_require_id') == 1 ? ' *' . _t('Required') : '' ) . '';

		$form->cf_email->move_into( $form->cf_commenterinfo );
		$form->cf_email->caption = _t( 'Email Address:' ) . '' . ( Options::get('comments_require_id') == 1 ? ' *' . _t('Required') : '' ) . '';

		$form->cf_url->move_into( $form->cf_commenterinfo );
		$form->cf_url->caption = _t( 'Web Address:' );

		$form->append('static','cf_disclaimer', _t( '
Email address is not published
') );
		$form->cf_disclaimer->move_into( $form->cf_commenterinfo );

		$form->append('fieldset', 'cf_contentbox', _t( 'Add to the Discussion' ) );
		$form->move_before($form->cf_contentbox, $form->cf_content);

		$form->cf_content->move_into($form->cf_contentbox);
	        $form->cf_content->caption = _t( 'Message: (Required)' );

		$form->cf_submit->caption = _t( 'Submit' );
	}

}

?>


code:
<?xml version="1.0" encoding="utf-8" ?>
<pluggable type="theme">
	<name>Mzingi</name>
	<license url="http://www.apache.org/licenses/LICENSE-2.0.html">Apache Software License 2.0</license>

	<author url="http://habariproject.org/">Habari Community</author>

	<version>1.0</version>
	<url>http://habariproject.org/</url>
	<description><![CDATA[Mzingi, Swahili for foundation, is intended as a clean, simple design that can be used
		as a framework for customization and theme development.]]></description>

	<template_engine>rawphpengine</template_engine>

	<copyright>2009</copyright>
</pluggable>


code:
*.exe
*.dll
*.[ao]
build/
.vscode/

repo_name: cptchuckles/g

path: .gitignore

license: unknown


code:
# /g/ battleships

Second code exercise from /g/: battleships with AI.
Using C++ with Simple and Fast Multimedia Library (SFML).


code:
battleships

there should be a board for each player: an array of spots (A-I,1-10), empty or full (with a ship). each player has 5 ships:
- aircraft carrier (5)
- battleship (4)
- destroyer (3)
- submarine (3)
- patrol (2)

the ships have to be lines of a consecutive length.

the player can place his ships one by one on his board. he should be able to enter [A..Z].\d. to place the ship and space to rotate the ship. there only have to be 2 orientations since the ships are just lengths of spots.

when the function is called for place the ship, it checks collision against OOB and other ships and if so it asks to choose again.

the computer gets to place his ships randomly.

the "choose place ship" callback will be called by the game state singleton. it will leverage polymorphism.

therefor there is a "player" class, and a "controller" interface. the user's controller class takes input from the mouse and screen. the AI's controller class just clicks randomly.

after ships are placed the game begins. player goes first.

moves are entered as [A..Z].\d. at this point there are no more "ships", only spots in the grids as empty or filled. hits are guesses on filled spots.

the AI will guess partially randomly at first. it must remember if it had a hit last, and if so what direction it took. it has to remember where all of its hits are, and group them by physical connectedness. once there are ship-groups in memory, the AI may randomly decide to revisit them if there is not a 100% certainty that it is not a destroyed ship.
 the first hit will have no direction. after the first hit, the computer will pick randomly 1 of the 4 adjacent cells. when it chooses one, it will also remember the opposite direction. if it is another hit, it remembers the direction it went in for that hit. if not, it chooses one of the other 3 spaces.
Assuming all player pieces remain:
 - after 2 consecutive hits, there is a 20% chance this is the patrol boat and it will strike randomly next. otherwise it will log 2 future spaces: the one in the same direction and the one on the opposite end of where it first hit (if open).
 - after 3 consecutive hits, there is a 50% chance this is either the submarine or the destroyer, and it will shoot randomly again.
 - after 4 consecutive hits, there is a 50% chance this is the battleship and it will shoot randomly again.
 - after 5 consecutive hits, this was the aircraft carrier, and it must shoot randomly again.
Subtract respective percentages based on how likely it is that another ship was sunk. This must be recalculated any time the AI decides to revisit a ship.
When the AI chooses to fire randomly again, it will tag the current ship with a percentage for how likely it was a finished ship.
This means the AI automatically has 5 "ship groups" in memory, but none of them are pre-marked for which ship they may be. The only tricky part is that there are two 4-space ships.

Each board keeps track of how many ship-spaces are left (it doesn't need to think about ships, only spaces). With each hit, the board queries if there are any other ship-spaces left. If not, the opposing player wins.

TODO LIST
- todo; ~ kindof did; x done

goal 1: get the screen to render boards
== GOAL MET: 31/10/2018
~ determine screen size
x create board class
	x create space struct (enum)
x draw 2 boards

goal 2: get player input
== GOAL MET: 3/11/2018 : 2 days ahead of deadline
x should be able to type in pos of cells to hit
	x input processed by prompt object that handles displaying prompt
x random cells in opponent's grid will be full but invisible to player
x misses will turn white and hits will turn red
x board will handle accepting a strike
	x board will check & return win condition
x i have to implement my own keyboard input buffer
	x it has to be updated every frame
	x it needs to keep track of which key was down last frame
	x on a new frame down, the key is added to the string
	x except backspace which reduces the buffer by 1 each stroke

goal 3: enable placement of player ships
== GOAL MET: 12/11/2018 DEADLINE: Tue 6/11/2018 (2 coding days late)
x enter a game mode where player places at least two ships
	x need to refactor main() to go into various game modes more seamlessly, keeping code flat
	x need modular functionality that has access to game resources
		x make everything global!
x use arrow keys to move and space to rotate it
x use return to set the ship
x ship should be confined to board bounds
x ships should detect overlap and refuse to set if overlapping
x will need a "ship laying" object
	x has a ship struct with length, rotation, and coordinates
	x has a ref to the board it will be laying ships on
	x can lay a ship of any length
	x will take player input
	x will have methods for auto-laying ships (for the AI)
		x this will replace the random-fill currently in place
x BUG: ship-laying object and prompt both independently test for return key, causing the player's first ship to be laid immediately at the request for a new game
	x must build input-tracking abstraction layer in which key-checks are eaten
	~ must check key-releases to re-enable certain keys, like return
		x achieved by boolean trickery

goal 4: enable enemy AI
== GOAL MET: pending DEADLINE: Tue, 20/11/2018
x enemy needs to attack player's board every turn
x implement lose condition
~ attacks will be semi-random UNTIL AI makes a successful hit
	x AI will not strike non-empty cells
	x AI will check adjacent cells of any random hit
	- AI will keep track, from smallest to largest, of which ships have probably been sunk
		- will count adjacencies and check for edges with misses
		~ maybe this testing will be a whole "mode" for the AI to be in in any given turn
	- AI will not strike in an open area smaller than the smallest non-sunk ship

i'm not going to implement all the ship-counting stuff.
Dumb AI works well enough: when it finds a hit, it checks adjacencies;
it then traces in the direction of the next adjacent hit;
when it runs into another miss, it revisits the first hit, and goes back
to checking adjacencies there in case it finds more.
If there are no more open adjacencies to the initial hit, it resumes
striking randomly.


code:
target=`grep "TARGET=" makefile | cut -d= -f2`

if [ -f $target ]; then
	rm -f $target
fi

if [ ! -d "build" ]; then
	mkdir build
fi

mingw32-make.exe all


code:
#TARGET is the name of the application
#Remove spaces for make.sh
TARGET=build/a.exe

#OBJS is the name(s) of the source files
OBJS = \
	src/main.o \
	src/Board.o \
	src/InputPrompt.o \
	src/ShipBuilder.o \
	src/KeyInput.o \
	src/AIController.o

#Paths
INCLUDE_PATHS = -IC:/tools/msys64/mingw64/include/SFML
LIB_PATHS = -LC:/tools/msys64/mingw64/lib

#Compiler and linker flags
COMPILER_FLAGS = -w -std=c++17 #-mwindows
LINKER_FLAGS = -llibsfml-graphics -llibsfml-audio -llibsfml-network -llibsfml-system -llibsfml-window

#Cleanup task
clean :
	rm -f build/*.exe src/*.o
	ls -RF

all : $(TARGET)
	ls build

#Build task:
$(TARGET) : $(OBJS)
	g++ -o $(TARGET) $(OBJS) $(INCLUDE_PATHS) $(LIB_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS)

#Build objects
%.o : %.cpp
	g++ -o $@ -c $< $(INCLUDE_PATHS) $(LIB_PATHS) $(COMPILER_FLAGS) $(LINKER_FLAGS)

#Define the prerequisites of each object
src/main.o : \
	src/Board.h \
	src/InputPrompt.h \
	src/ShipBuilder.h \
	src/KeyInput.h \
	src/AIController.h

src/AIController.o : \
	src/AIController.h \
	src/Board.h

src/ShipBuilder.o : \
	src/ShipBuilder.h \
	src/KeyInput.h \
	src/Utility.h

src/Board.o : \
	src/Board.h \
	src/IDrawable.h \
	src/Utility.h

src/InputPrompt.o : \
	src/InputPrompt.h \
	src/IDrawable.h \
	src/KeyInput.h

path: makefile


code:
/**
 * AI Controller implementation
 */

#include "AIController.h"
#include "Utility.h"
#include "Board.h"

AIController::AIController(Board& target, int delay) : target{target}, delay{delay}
{
	auto dim = target.GetDimensions();

	cols = dim.col;
	rows = dim.row;

	clock_gettime(CLOCK_REALTIME, &timestamp);
}

bool AIController::Strike()
{
	if(!CheckDelayTimer()) return false;

	auto c = CalculateCell();

	if(target.Attack(c))
	{
		last_hit = std::optional(c);

		switch(mode)
		{
		case Mode::RAND :
			cold_hit = std::optional(c);
			try_cells = GetAdjacentCells(c);
			mode = Mode::SEARCH;
			break;
		case Mode::SEARCH :
			rel_move = last_hit.value() - cold_hit.value();
			mode = Mode::TRACE;
		}
	} else {
		if(mode==Mode::TRACE) mode = Mode::SEARCH;
	}

	myturn = false;

	return true;
}

Board::Cell AIController::CalculateCell()
{
	Board::Cell c;

	switch(mode)
	{
	case Mode::RAND :
		c = RandomValidCell();
		break;

	case Mode::SEARCH :
		if(try_cells.size() > 0) {
			int i = util::Rand(0, try_cells.size()-1);
			c = try_cells.at(i);
			try_cells.erase(try_cells.begin()+i);
		} else {
			mode = Mode::RAND;
			c = RandomValidCell();
		}
		break;

	case Mode::TRACE :
		auto oc = NextCellInTrace();
		if(oc) c = oc.value();
		else {
			mode = Mode::SEARCH;
			c = CalculateCell();
		}
	}

	return c;
}

Board::Cell AIController::RandomValidCell() const
{
	Board::Cell try_cell;
	do
	{
		try_cell.col = util::Rand(0, cols-1);
		try_cell.row = util::Rand(0, rows-1);
	}
	while( !CheckCellValid(try_cell) );

	return try_cell;
}

std::optional<Board::Cell> AIController::NextCellInTrace() const
{
	if(!last_hit) return { RandomValidCell() };

	auto cell = last_hit.value() + rel_move;

	if(! CheckCellValid(cell)) return std::nullopt;

	return {cell};
}

std::vector<Board::Cell> AIController::GetAdjacentCells(const Board::Cell& cell)
{
	std::vector<Board::Cell> cells;
	auto check = cell;

	check.col--;
	if(CheckCellValid(check)) cells.push_back(check);
	check.col+=2;
	if(CheckCellValid(check)) cells.push_back(check);
	check.col--;
	check.row--;
	if(CheckCellValid(check)) cells.push_back(check);
	check.row+=2;
	if(CheckCellValid(check)) cells.push_back(check);

	return cells;
}

bool AIController::CheckCellValid(const Board::Cell& cell) const
{
	auto optcell = target.GetCell(cell.col, cell.row);

	if(!optcell) return false;

	auto cellv = optcell.value();

	return ( cellv != Board::CellType::MISS
		&& cellv != Board::CellType::HIT );
}

bool AIController::isMyTurn() const
{
	return myturn;
}

void AIController::ActivateTurn()
{
	clock_gettime(CLOCK_REALTIME, &timestamp);
	myturn = true;
}

bool AIController::CheckDelayTimer()
{
	struct timespec tm;
	clock_gettime(CLOCK_REALTIME, &tm);

	return ((tm.tv_sec - timestamp.tv_sec) >= delay);
}


code:
/**
 * AI Controller class.
 */

#pragma once
#include <ctime>
#include <optional>
#include <vector>
#include "Board.h"

class AIController
{
	Board& target;
	int cols, rows, delay;

	enum class Mode {
		RAND,
		SEARCH,
		TRACE
	};

	std::optional<Board::Cell> cold_hit = std::nullopt;
	std::optional<Board::Cell> last_hit = std::nullopt;
	Board::Cell rel_move = {0,0};
	std::vector<Board::Cell> try_cells;
	bool streak = false;
	Mode mode = Mode::RAND;

	struct timespec timestamp;
	bool myturn = false;
	bool CheckDelayTimer();

	bool CheckCellValid(const Board::Cell& cell) const;
	std::vector<Board::Cell> GetAdjacentCells(const Board::Cell& cell);
	Board::Cell RandomValidCell() const;
	std::optional<Board::Cell> NextCellInTrace() const;
	Board::Cell CalculateCell();

public:
	AIController() = delete;
	AIController(Board& target, int delay);

	bool Strike();
	bool isMyTurn() const;
	void ActivateTurn();
};


code:
/**
 * Board implementation
 */

#include <SFML/Graphics.hpp>
#include "Utility.h"
#include "Board.h"

void Board::SetDisplayResource(sf::Text* TextResource)
{
	display = TextResource;
}

void Board::SetHidden(bool hide)
{
	hidden = hide;
}

void Board::SetDraw(bool d)
{
	draw = d;
}

void Board::Clear()
{
	std::fill(grid.begin(), grid.end(), CellType::OPEN);
}

void Board::Draw(sf::RenderTarget& target) const
{
	if(!draw) return;

	bool hasDisplay = (display != nullptr);

	// Grid is cols by rows
	for(int r=0; r<rows; r++)
	{
		int dy = cell_size * r;
		dy += y;

		if(hasDisplay){
			display->setString(std::to_string(r));
			display->setPosition(x-cell_size, dy);
			target.draw(*display);
		}

		for(int c=0; c<cols; c++)
		{
			int dx = cell_size * c;
			dx += x;

			if(hasDisplay){
				display->setString((char)((int)'A'+c));
				display->setPosition(dx, y-cell_size);
				target.draw(*display);
			}

			open_cell.setPosition(dx, dy);
			full_cell.setPosition(dx, dy);
			miss_cell.setPosition(dx, dy);
			hit_cell.setPosition(dx, dy);

			int cell = cols*r+c;

			switch(grid.at(cell)) {
			case CellType::OPEN:
				target.draw(open_cell);
				break;
			case CellType::FULL:
				hidden ? target.draw(open_cell) : target.draw(full_cell);
				break;
			case CellType::MISS:
				target.draw(miss_cell);
				break;
			case CellType::HIT:
				target.draw(hit_cell);
			};
		} // for c
	} // for r
}

bool Board::SetCell(int col, int row, CellType type)
{
	if(col > cols-1 || row > rows-1 || col < 0 || row < 0)
		return false;

	int cell = cols*row + col;
	grid.at(cell) = type;

	return true;
}

std::optional<Board::CellType> Board::GetCell(int col, int row) const
{
	if(col > cols-1 || row > rows-1 || col < 0 || row < 0)
		return std::nullopt;

	int cell = cols*row + col;
	return { grid.at(cell) };
}

std::optional<Board::Cell> Board::GetCellFromString(std::string input) const
{
	Cell cell = { 0,0 };

	if(input.length() > 2) return std::nullopt;

	try {
		cell.row = std::stoi(std::string{input[1]});
	} catch(...) {
		return std::nullopt;
	}

	std::string validchars;
	for(int i=0; i<cols; i++)
		validchars.push_back('A'+i);

	cell.col = validchars.find(input[0]);

	if(cell.col == std::string::npos)
		return std::nullopt;

	return {cell};
}

Board::Cell Board::GetDimensions() const
{
	return {cols, rows};
}

bool Board::Attack(Cell cell)
{
	return Attack(cell.col, cell.row);
}

bool Board::Attack(int col, int row)
{
	auto cell = GetCell(col, row);
	if(!cell) return false;

	switch (cell.value())
	{
	case CellType::FULL :
		SetCell(col, row, CellType::HIT);
		return true;
	case CellType::HIT :
		return false;
	default :
		SetCell(col, row, CellType::MISS);
	}

	return false;
}

bool Board::CheckDefeated() const
{
	for(auto c : grid)
		if(c == CellType::FULL)
			return false;

	return true;
}

void Board::RandomFill(unsigned int qt)
{
	// qt > grid.size() will infinitely loop.
	if(qt > grid.size()) return;

	for(int i=0; i<qt; i++) {
		int c = util::Rand(0, grid.size()-1);
		while(grid.at(c) == CellType::FULL)
			c = util::Rand(0, grid.size()-1);

		grid.at(c) = CellType::FULL;
	}
}


code:
/**
 * The battlefield grid of 90 spaces
 */

#pragma once

#include <vector>
#include <optional>
#include "IDrawable.h"

namespace sf {
	class Shape;
	class Text;
	class RenderTarget;
}

class Board : public IDrawable
{
public:
	enum CellType {
		OPEN,
		FULL,
		MISS,
		HIT
	};

	struct Cell {
		int col, row;
		bool operator==(Cell const& in) { return (col==in.col && row==in.row); }
		bool operator!=(Cell const& in) { return !operator==(in); }
		friend Cell operator+(const Cell& a, const Cell& b) { return std::move(Cell{a.col+b.col, a.row+b.row}); }
		friend Cell operator-(const Cell& a, const Cell& b) { return std::move(Cell{a.col-b.col, a.row-b.row}); }
	};

private:
	int cols, rows;
	int x, y;
	int cell_size;
	bool hidden = false;
	bool draw = true;
	std::vector<CellType> grid;

	sf::Shape& open_cell;
	sf::Shape& full_cell;
	sf::Shape& miss_cell;
	sf::Shape& hit_cell;
	sf::Text* display = nullptr;

public:
	Board(int cellsize, int cols, int rows, int x, int y,
		sf::Shape& open,
		sf::Shape& full,
		sf::Shape& miss,
		sf::Shape& hit) : cell_size{cellsize}, cols{cols}, rows{rows}, x{x}, y{y}, open_cell{open}, full_cell{full}, miss_cell{miss}, hit_cell{hit}
	{
		int size = rows*cols;
		grid.reserve(size);
		std::fill_n(std::back_inserter(grid), size, CellType::OPEN);
	}
	~Board() {
		grid.clear();
	}

	bool SetCell(int col, int row, CellType);
	std::optional<CellType> GetCell(int col, int row) const;
	std::optional<Cell> GetCellFromString(std::string input) const;
	Cell GetDimensions() const;

	bool Attack(int col, int row);
	bool Attack(Cell);
	bool CheckDefeated() const;

	void SetDisplayResource(sf::Text* TextResource);
	void SetHidden(bool);
	void SetDraw(bool);

	void Draw(sf::RenderTarget& target) const override;

	void RandomFill(unsigned int qt);
	void Clear();

};


code:
/**
 * IDrawable interface for objects which can draw to screen.
 * I had to roll my own interface because sf::Drawable prevents
 * polymorphism.
 */

#pragma once

namespace sf {
	class RenderTarget;
}

class IDrawable
{
public:
	virtual void Draw(sf::RenderTarget& target) const = 0;
};


code:
/**
 * Input Prompt implementation
 */

#include <SFML/Graphics.hpp>
#include <SFML/Window/Keyboard.hpp>
#include "InputPrompt.h"
#include "KeyInput.h"

void InputPrompt::Update()
{
	// sf::Keyboard::Key enum stores A-Z,0-9 as (int)0-35
	// Create an ASCII representation of it here:
	static std::string keylist = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

	for(int k=0; k<=35; k++)
	{
		auto key = (sf::Keyboard::Key)k;
		if(KeyInput::Get().KeyPressed(key)) buffer += keylist[k];
	}

	if(KeyInput::Get().KeyPressed(sf::Keyboard::Key::Backspace))
		if(buffer.length() > 0) buffer.erase(buffer.length()-1);
}

std::string InputPrompt::GetContent()
{
	return buffer;
}

void InputPrompt::ClearInput()
{
	buffer.clear();
}

void InputPrompt::SetPos(int newx, int newy)
{
	x = newx;
	y = newy;
}

void InputPrompt::SetCaption(std::string newCap)
{
	caption = newCap;
}

void InputPrompt::Draw(sf::RenderTarget& target) const
{
	display.setPosition((float)x, (float)y);
	display.setString(caption + buffer);
	target.draw(display);
}


code:
/**
 * Input Prompt object
 * handles taking input from player
 */

#pragma once

#include <string>
#include "IDrawable.h"

namespace sf {
	class Text;
	class RenderTarget;
}

class InputPrompt : public IDrawable
{
	sf::Text& display;
	std::string caption;
	std::string buffer;

	int x, y;

public:

	InputPrompt(std::string caption, sf::Text& TextResource, int x=0, int y=0) : caption{caption}, display{TextResource}, x{x}, y{y}
	{}

	void Update();
	std::string GetContent();
	void ClearInput();
	void SetPos(int newx, int newy);

	void SetCaption(std::string newCap);
	void Draw(sf::RenderTarget& target) const override;
};


code:
/**
 * Keyboard Input implementation
 */

#include "KeyInput.h"

KeyInput& KeyInput::Get()
{
	static KeyInput instance;

	return instance;
}

void KeyInput::Update()
{
	for(auto& [key, keypress] : keys)
	{
		bool down = sf::Keyboard::isKeyPressed(key);

		keypress.pressed = false;
		if(down && !keypress.isdown)
			keypress.pressed = true;

		keypress.isdown = down;
	}
}

bool KeyInput::KeyPressed(sf::Keyboard::Key key)
{
	bool result = false;
	try {
		result = keys.at(key).pressed;
	} catch(...) {
		keys.emplace(key, Keystroke{false,false});
		return false;
	}

	keys.at(key).pressed = false; // Eat input
	return result;
}

bool KeyInput::Return()
{
	return KeyPressed(sf::Keyboard::Key::Return);
}


code:
/**
 * Keyboard Input handler singleton.
 * Will record all keypresses and eat them upon check.
 */

#pragma once

#include <map>
#include <SFML/Window/Keyboard.hpp>

class KeyInput
{
public:
	struct Keystroke {
		bool pressed=false;
		bool isdown=false;
	};

private:
	std::map<sf::Keyboard::Key, Keystroke> keys;

	KeyInput() {};
public:
	KeyInput(KeyInput const&)		= delete;
	KeyInput(KeyInput const&&)		= delete;
	void operator=(KeyInput const&)	= delete;

	static KeyInput& Get();

	void Update();
	bool KeyPressed(sf::Keyboard::Key key);
	bool Return(); // Special case for brevity
};


code:
/**
 * Ship Builder implementation.
 */

#include <SFML/Graphics.hpp>
#include <algorithm>
#include "ShipBuilder.h"
#include "KeyInput.h"
#include "Utility.h"

ShipBuilder::Ship* ShipBuilder::GetShip() const
{
	return ship;
}

bool ShipBuilder::ConstructShip(unsigned int length)
{
	if(ship) return false;
	if(length == 0 || (length > rows && length > cols)) return false;

	ship = new Ship {0,0, length, (length > cols)};

	return true;
}

bool ShipBuilder::CheckSpaceFree(Ship& s) const
{
	int c = s.col;
	int r = s.row;
	for(int i=0; i<s.length; i++)
	{
		if(board.GetCell(c,r).value() == Board::CellType::FULL) return false;
		c += !s.vertical;
		r += s.vertical;
	}

	return true;
}

void ShipBuilder::Update(sf::RenderTarget& target)
{
	if(!ship) return;

	auto& kb = KeyInput::Get();

	// Movement deltas
	int dc = kb.KeyPressed(sf::Keyboard::Key::Right) - kb.KeyPressed(sf::Keyboard::Key::Left);
	int dr = kb.KeyPressed(sf::Keyboard::Key::Down) - kb.KeyPressed(sf::Keyboard::Key::Up);

	if(kb.KeyPressed(sf::Keyboard::Key::Space))
		FlipShip();

	ship->col += dc;
	ship->row += dr;

	ConfineShipToBoard();
	DrawBoard(target);
}

void ShipBuilder::ConfineShipToBoard()
{
	if(!ship) return;

	int goodcols = ship->vertical ? cols-1 : (cols - ship->length);
	int goodrows = ship->vertical ? (rows - ship->length) : rows-1;

	ship->col = std::clamp(ship->col, 0, goodcols);
	ship->row = std::clamp(ship->row, 0, goodrows);
}

void ShipBuilder::FlipShip()
{
	if(!ship) return;

	ship->vertical = !ship->vertical;

	ConfineShipToBoard();
}

bool ShipBuilder::FinalizeShip()
{
	if(!ship) return false;
	if(!CheckSpaceFree(*ship)) return false;

	int c = ship->col;
	int r = ship->row;
	for(int i=0; i<ship->length; i++)
	{
		board.SetCell(c,r, Board::CellType::FULL);
		c += !ship->vertical;
		r += ship->vertical;

		ConfineShipToBoard();
	}

	delete ship;
	ship = nullptr;

	return true;
}

void ShipBuilder::DrawBoard(sf::RenderTarget& target)
{
	Board temp = board;
	temp.SetDraw(true);

	if(ship)
	{
		int c = ship->col;
		int r = ship->row;
		for(int i=0; i < ship->length; i++)
		{
			if(temp.GetCell(c,r).value() == Board::CellType::FULL)
				temp.SetCell(c,r, Board::CellType::HIT);
			else
				temp.SetCell(c,r, Board::CellType::MISS);

			c += !ship->vertical;
			r += ship->vertical;
		}
	} // if ship

	temp.Draw(target);
}

bool ShipBuilder::RandomShip(unsigned int length)
{
	if(! ConstructShip(length)) return false;

	ship->col = util::Rand(0, cols-1);
	ship->row = util::Rand(0, rows-1);
	ship->vertical = util::Rand(0, 1);
	ConfineShipToBoard();

	while(!CheckSpaceFree(*ship)) {
		ship->col = util::Rand(0, cols-1);
		ship->row = util::Rand(0, rows-1);
		ship->vertical = util::Rand(0, 1);
		ConfineShipToBoard();
	}

	FinalizeShip();

	return true;
}


code:
/**
 * Ship Builder class.
 * Not the "builder" design pattern.
 * It handles laying ships of variable length onto a board.
 */

#pragma once

#include <SFML/Window/Keyboard.hpp>
#include "Board.h"

namespace sf {
	class RenderTarget;
}

class ShipBuilder
{
public:
	struct Ship {
		int col,row, length;
		bool vertical;
	};

private:
	Board& board;
	int cols, rows;
	Ship* ship = nullptr;

	void FlipShip();
	void ConfineShipToBoard();
	bool CheckSpaceFree(Ship&) const;
	void DrawBoard(sf::RenderTarget& target);

public:
	ShipBuilder(Board& board) : board{board}
	{
		board.SetDraw(false);

		auto size = board.GetDimensions();
		cols = size.col;
		rows = size.row;
	}
	~ShipBuilder()
	{
		if(ship) {
			if(!FinalizeShip()) {
				delete ship;
				ship = nullptr;
			}
		}

		board.SetDraw(true);
	}

	void Update(sf::RenderTarget& target);

	bool ConstructShip(unsigned int length);
	bool RandomShip(unsigned int length);
	bool FinalizeShip();

	Ship* GetShip() const;
};


code:
/**
 * Utility function(s).
 * Need to stop repeating my random number code so I'm putting it here.
 */

#ifndef BATTLESHIP_UTILITY
#define BATTLESHIP_UTILITY

#include <ctime>
#include <random>

namespace util
{
	inline int Rand(int low, int high)
	{
		// Get system time resource
		struct timespec tm;
		clock_gettime(CLOCK_REALTIME, &tm);

		// Get rand num generator engine & functor with clock nanosec as seed
		static std::minstd_rand0 e{tm.tv_nsec};
		std::uniform_int_distribution<int> ud{low, high};

		return ud(e);
	}
};

#endif //BATTLESHIP_UTILITY


code:
/**
 * /g/ Coding challenge: Battleships with AI
 */

#include <SFML/Graphics.hpp>
#include "Board.h"
#include "AIController.h"
#include "InputPrompt.h"
#include "ShipBuilder.h"
#include "KeyInput.h"

const int CellSize = 32; //pixels

const int WindowWidth = 10*CellSize;
const int WindowHeight = 24*CellSize;
const int shipSizes[] = {2,3,3,4,5};

enum class GameState {
	SETUP,
	PLAY,
	END
};

GameState state = GameState::SETUP;

sf::RenderWindow window = {
	sf::VideoMode(WindowWidth, WindowHeight),
	"/g/ battleships"
};

sf::Font arial;
sf::Text caption = {"aeiou", arial, (CellSize*3)/4};
InputPrompt prompt = {"wew lads", caption, 0,23*CellSize};

sf::CircleShape open{CellSize/2};
sf::CircleShape full{CellSize/2};
sf::CircleShape miss{CellSize/2};
sf::CircleShape hit{CellSize/2};

Board board_1 {CellSize, 9,10,
               CellSize,CellSize,
							 open, full, miss, hit};
Board board_2 {CellSize, 9,10,
               CellSize,CellSize * 12,
							 open, full, miss, hit};
//Board board_2{CellSize, 9,10, CellSize,192, open, full, miss, hit}; //64,770
AIController ai = {board_2, 2};

std::vector<IDrawable*> renderer;

bool init();
void gameReset();
void gameSetup();
void buildEnemyShips();
void inPlay();
void enemyTurn();
void atEndScreen();

int main()
{
	if(! init()) return 1;

	while (window.isOpen())
	{
		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
				window.close();
		}

		window.clear();
		KeyInput::Get().Update();

		switch(state)
		{
		case GameState::SETUP :
			gameSetup();
			break;
		case GameState::PLAY :
			inPlay();
			break;
		case GameState::END :
			atEndScreen();
			break;
		}

		for(auto item : renderer) item->Draw(window);

		window.display();
	}

	return 0;
}

bool init()
{
	window.setFramerateLimit(60);

	if(! arial.loadFromFile("c:/windows/fonts/arial.ttf"))
		return false;

	open.setFillColor(sf::Color::Blue);
	full.setFillColor(sf::Color{128,128,128,255});
	miss.setFillColor(sf::Color::White);
	hit.setFillColor(sf::Color::Red);

	board_1.SetDisplayResource(&caption);
	board_2.SetDisplayResource(&caption);

	board_1.SetHidden(true);

	renderer.push_back(&board_1);
	renderer.push_back(&board_2);
	renderer.push_back(&prompt);

	return true;
}

void gameReset()
{
	board_1.Clear();
	board_1.SetHidden(true);
	board_2.Clear();
	prompt.ClearInput();
	state = GameState::SETUP;
}

void gameSetup()
{
	prompt.SetCaption("Arrows, space, & return");

	static ShipBuilder* builder = nullptr;
	static int ships = 4;

	if(! builder) builder = new ShipBuilder{board_2};

	if(! builder->GetShip()) builder->ConstructShip(shipSizes[ships]);

	builder->Update(window);

	if(KeyInput::Get().Return())
	{
		if(builder->FinalizeShip())
			ships--;

		if(ships < 0)
		{
			ships = 4;
			delete builder;
			builder = nullptr;
			buildEnemyShips();
			state = GameState::PLAY;
		}
	}
}

void buildEnemyShips()
{
	ShipBuilder builder = {board_1};

	for(int i=0; i<5; i++)
		builder.RandomShip(shipSizes[i]);
}

void inPlay()
{
	if(ai.isMyTurn()) {
		enemyTurn();
		return;
	}

	prompt.SetCaption("Try cell: ");
	prompt.Update();

	if(KeyInput::Get().Return())
	{
		auto cell = board_1.GetCellFromString(prompt.GetContent());
		prompt.ClearInput();

		if(! cell) return;

		board_1.Attack(cell.value());

		if(board_1.CheckDefeated()) {
			prompt.SetCaption("You Win! Again? (y/n): ");
			state = GameState::END;
			return;
		}

		ai.ActivateTurn();
	}
}

void enemyTurn()
{
	prompt.SetCaption("Enemy AI thinking...");

	if(ai.Strike()) {
		if(board_2.CheckDefeated()) {
			prompt.SetCaption("You Lost! Again? (y/n): ");
			state = GameState::END;
		}
	}
}

void atEndScreen()
{
	board_1.SetHidden(false);
	prompt.Update();

	if(KeyInput::Get().Return())
	{
		auto answer = prompt.GetContent();

		if(answer=="Y")
			gameReset();
		else if(answer=="N")
			window.close();
	}
}


code:
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain

path: .gitattributes


code:
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
#.pdn

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush personal settings
.cr/personal

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Local History for Visual Studio
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb

*.psd
*.dds
*.pdn


code:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
</configuration>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
<!-- Obsoleted
  <RJW_Menstruation.DNADef>
    <defName>Human</defName>
    <label>human fetus</label>
	<fetusTexPath>Fetus/Fetus_Default</fetusTexPath>
	<cumThickness>0.2</cumThickness>
-->

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<ThingDef ParentName="MakeableDrugPillBase">
		<defName>OvaryRegenerationPill</defName>
		Ovary regeneration pill
		<description>Recovers ovary's health.
Less effective on unhealthy ovary.
Does not recover menopause.</description>
		<graphicData>
			<texPath>Things/Item/ORPill</texPath>
			<graphicClass>Graphic_StackCount</graphicClass>
		</graphicData>
		<rotatable>false</rotatable>
		<statBases>
			<WorkToMake>2400</WorkToMake>
			<MarketValue>160</MarketValue>
			<Mass>0.05</Mass>
		</statBases>
		<techLevel>Industrial</techLevel>
		<ingestible>
			<drugCategory>Medical</drugCategory>
			<outcomeDoers>

					<effectOffset>0.3</effectOffset>

			</outcomeDoers>
		</ingestible>
		<recipeMaker>
			<researchPrerequisite>DrugProduction</researchPrerequisite>
			<recipeUsers>

DrugLab

			</recipeUsers>
		</recipeMaker>
		<costList>
			<MedicineHerbal>10</MedicineHerbal>
			<Neutroamine>4</Neutroamine>
			<InsectJelly>8</InsectJelly>
		</costList>
		<comps>

			<addictiveness>0</addictiveness>
			<listOrder>1000</listOrder>
				<overdoseSeverityOffset>
					<min>0.08</min>
					<max>0.14</max>
				</overdoseSeverityOffset>

		</comps>
	</ThingDef>

	<ThingDef ParentName="MakeableDrugPillBase">
		<defName>SuperovulationInducingAgent</defName>
		Superovulation inducing agent
		<description>Induce superovulation

May cause early menopause</description>
		<graphicData>
			<texPath>Things/Item/SIA</texPath>
			<graphicClass>Graphic_StackCount</graphicClass>
		</graphicData>
		<rotatable>false</rotatable>
		<statBases>
			<WorkToMake>2400</WorkToMake>
			<MarketValue>140</MarketValue>
			<Mass>0.05</Mass>
		</statBases>
		<techLevel>Industrial</techLevel>
		<ingestible>
			<drugCategory>Medical</drugCategory>
			<outcomeDoers>

			</outcomeDoers>
		</ingestible>
		<recipeMaker>
			<researchPrerequisite>DrugProduction</researchPrerequisite>
			<recipeUsers>

DrugLab

			</recipeUsers>
		</recipeMaker>
		<costList>
			<MedicineHerbal>12</MedicineHerbal>
			<Neutroamine>6</Neutroamine>
		</costList>
		<comps>

			<addictiveness>0</addictiveness>
			<listOrder>1000</listOrder>
				<overdoseSeverityOffset>
					<min>0.08</min>
					<max>0.14</max>
				</overdoseSeverityOffset>

		</comps>
	</ThingDef>

	<ThingDef ParentName="MakeableDrugPillBase">
		<defName>PainReliever</defName>
		Pain reliever
		<description>Relieves menstrual pain for a day.

Also effective on generic pain.</description>
		<graphicData>
			<texPath>Things/Item/PainReliever</texPath>
			<graphicClass>Graphic_StackCount</graphicClass>
		</graphicData>
		<rotatable>false</rotatable>
		<statBases>
			<WorkToMake>1000</WorkToMake>
			<MarketValue>12</MarketValue>
			<Mass>0.01</Mass>
		</statBases>
		<techLevel>Industrial</techLevel>
		<ingestible>
			<drugCategory>Medical</drugCategory>
			<outcomeDoers>

					<hediffDef>Hediff_PainReliever</hediffDef>
					<severity>1.0</severity>

			</outcomeDoers>
		</ingestible>
		<recipeMaker>
			<researchPrerequisite>DrugProduction</researchPrerequisite>
			<recipeUsers>

DrugLab

			</recipeUsers>
		</recipeMaker>
		<costList>
			<MedicineHerbal>1</MedicineHerbal>
		</costList>
		<comps>

			<addictiveness>0</addictiveness>
			<listOrder>1000</listOrder>
				<overdoseSeverityOffset>
					<min>0.08</min>
					<max>0.14</max>
				</overdoseSeverityOffset>

		</comps>
	</ThingDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<HediffDef Name="Hediff_MenstrualCramp">
		<hediffClass>HediffWithComps</hediffClass>
		<defName>Hediff_MenstrualCramp</defName>
		In period
		<labelNoun>in period</labelNoun>
		<description>in period</description>
		<defaultLabelColor>(0.70,0.00,0.00)</defaultLabelColor>
		<isBad>true</isBad>
		<tendable>false</tendable>
		<makesSickThought>false</makesSickThought>
		<makesAlert>false</makesAlert>
		<maxSeverity>1</maxSeverity>
		<initialSeverity>0.1</initialSeverity>
		<injuryProps>
			<canMerge>true</canMerge>
		</injuryProps>
		<stages>

				unpleasant
				<statFactors>
					<SexFrequency>0.50</SexFrequency>
					<SexSatisfaction>0.95</SexSatisfaction>
				</statFactors>
				<painOffset>0.005</painOffset>

				<minSeverity>0.2</minSeverity>
				annoying
				<statFactors>
					<SexFrequency>0.40</SexFrequency>
					<SexSatisfaction>0.95</SexSatisfaction>
				</statFactors>
				<painOffset>0.01</painOffset>

				<minSeverity>0.4</minSeverity>
				aching
				<statFactors>
					<SexFrequency>0.20</SexFrequency>
					<SexSatisfaction>0.95</SexSatisfaction>
				</statFactors>
				<painOffset>0.10</painOffset>

				<minSeverity>0.6</minSeverity>
				painful
				<statFactors>
					<SexFrequency>0.0</SexFrequency>
					<SexSatisfaction>0.95</SexSatisfaction>
				</statFactors>
				<painOffset>0.20</painOffset>

		</stages>
		<comps>

				<severityPerDay>-0.1</severityPerDay>

		</comps>
	</HediffDef>

	<HediffDef Name="Hediff_Menopause">
		<hediffClass>HediffWithComps</hediffClass>
		<defName>Hediff_Menopause</defName>
		Menopause
		<labelNoun>menopause</labelNoun>
		<description>reached menopause</description>
		<labelNounPretty>{0} reached menopause</labelNounPretty>
		<defaultLabelColor>(0.70,0.70,0.00)</defaultLabelColor>
		<isBad>false</isBad>
		<tendable>false</tendable>
		<makesSickThought>false</makesSickThought>
		<makesAlert>true</makesAlert>
		<maxSeverity>1</maxSeverity>
		<initialSeverity>0.1</initialSeverity>
		<injuryProps>
			<canMerge>true</canMerge>
		</injuryProps>
		<stages>

				<statFactors>
					<SexFrequency>0.01</SexFrequency>
					<SexSatisfaction>0.50</SexSatisfaction>
				</statFactors>
				<capMods>

						<capacity>RJW_Fertility</capacity>
						<postFactor>0.00</postFactor>

				</capMods>

		</stages>
		<comps>
		</comps>
	</HediffDef>

	<HediffDef Name="Hediff_Climacteric">
		<hediffClass>HediffWithComps</hediffClass>
		<defName>Hediff_Climacteric</defName>
		Climacteric
		<labelNoun>climacteric</labelNoun>
		<description>climacteric</description>
		<defaultLabelColor>(0.70,0.70,0.00)</defaultLabelColor>
		<isBad>false</isBad>
		<tendable>false</tendable>
		<makesSickThought>false</makesSickThought>
		<makesAlert>false</makesAlert>
		<maxSeverity>1</maxSeverity>
		<initialSeverity>0.1</initialSeverity>
		<injuryProps>
			<canMerge>true</canMerge>
		</injuryProps>
		<stages>

				early
				<statFactors>
					<SexFrequency>0.50</SexFrequency>
					<SexSatisfaction>0.8</SexSatisfaction>
				</statFactors>
				<capMods>

						<capacity>RJW_Fertility</capacity>
						<postFactor>0.50</postFactor>

				</capMods>

				middle
				<minSeverity>0.2</minSeverity>
				<statFactors>
					<SexFrequency>0.25</SexFrequency>
					<SexSatisfaction>0.7</SexSatisfaction>
				</statFactors>
				<capMods>

						<capacity>RJW_Fertility</capacity>
						<postFactor>0.25</postFactor>

				</capMods>

				latter
				<minSeverity>0.4</minSeverity>
				<statFactors>
					<SexFrequency>0.10</SexFrequency>
					<SexSatisfaction>0.6</SexSatisfaction>
				</statFactors>
				<capMods>

						<capacity>RJW_Fertility</capacity>
						<postFactor>0.10</postFactor>

				</capMods>

				end
				<minSeverity>0.6</minSeverity>
				<statFactors>
					<SexFrequency>0.05</SexFrequency>
					<SexSatisfaction>0.5</SexSatisfaction>
				</statFactors>
				<capMods>

						<capacity>RJW_Fertility</capacity>
						<postFactor>0.01</postFactor>

				</capMods>

		</stages>
		<comps>
		</comps>
	</HediffDef>

	<HediffDef Name="Hediff_Estrus">
		<hediffClass>HediffWithComps</hediffClass>
		<defName>Hediff_Estrus</defName>
		Estrus
		<labelNoun>estrus</labelNoun>
		<description>estrus</description>
		<defaultLabelColor>(1.00,0.60,0.75)</defaultLabelColor>
		<isBad>false</isBad>
		<tendable>false</tendable>
		<makesSickThought>false</makesSickThought>
		<makesAlert>false</makesAlert>
		<maxSeverity>10000</maxSeverity>
		<initialSeverity>1.0</initialSeverity>
		<injuryProps>
			<canMerge>true</canMerge>
		</injuryProps>
		<stages>

				<statFactors>
					<SexFrequency>5.0</SexFrequency>
					<SexSatisfaction>1.5</SexSatisfaction>
				</statFactors>

		</stages>
		<comps>

				<severityPerDay>-1.0</severityPerDay>

		</comps>
	</HediffDef>

	<HediffDef Name="Hediff_Estrus_Consealed">
		<hediffClass>HediffWithComps</hediffClass>
		<defName>Hediff_Estrus_Consealed</defName>
		Estrus(consealed)
		<labelNoun>estrus</labelNoun>
		<description>estrus</description>
		<defaultLabelColor>(1.00,0.60,0.75)</defaultLabelColor>
		<isBad>false</isBad>
		<tendable>false</tendable>
		<makesSickThought>false</makesSickThought>
		<makesAlert>false</makesAlert>
		<maxSeverity>10000</maxSeverity>
		<initialSeverity>1.0</initialSeverity>
		<injuryProps>
			<canMerge>true</canMerge>
		</injuryProps>
		<stages>

				<becomeVisible>false</becomeVisible>
				<statFactors>
					<SexFrequency>1.10</SexFrequency>
					<SexSatisfaction>1.05</SexSatisfaction>
				</statFactors>

		</stages>
		<comps>

				<severityPerDay>-1.0</severityPerDay>

		</comps>
	</HediffDef>

	<HediffDef Name="Hediff_PainReliever">
		<hediffClass>HediffWithComps</hediffClass>
		<defName>Hediff_PainReliever</defName>
		Pain reliever
		<description>relieves pain.</description>
		<defaultLabelColor>(0.75,0.75,1.0)</defaultLabelColor>
		<isBad>false</isBad>
		<tendable>false</tendable>
		<makesSickThought>false</makesSickThought>
		<makesAlert>false</makesAlert>
		<maxSeverity>5</maxSeverity>
		<initialSeverity>1.0</initialSeverity>
		<stages>

				<painOffset>-0.1</painOffset>

		</stages>
		<comps>

				<severityPerDay>-1.0</severityPerDay>

		</comps>
	</HediffDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<JobDef Name="VaginaWashing">
		<defName>VaginaWashing</defName>
		<driverClass>RJW_Menstruation.JobDriver_VaginaWashing</driverClass>
		<reportString>washing vagina</reportString>
		<casualInterruptible>true</casualInterruptible>
	</JobDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
	<JobDef>
		<defName>LactateSelf</defName>
		<driverClass>RJW_Menstruation.JobDriver_MilkSelf</driverClass>
		<reportString>lactating self</reportString>
		<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
	</JobDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
  <KeyBindingDef ParentName="GameKeyBinding">
    <defName>OpenStatusWindow</defName>
    <label>menstruation: open status window</label>
    <defaultKeyCodeA>Q</defaultKeyCodeA>
  </KeyBindingDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
  <RecipeDef Abstract="True" Name="BaseBreastSurgery">
    <effectWorking>Surgery</effectWorking>
    <soundWorking>Recipe_Surgery</soundWorking>
    <workSpeedStat>MedicalOperationSpeed</workSpeedStat>
    <workSkill>Medicine</workSkill>
    <workSkillLearnFactor>0.2</workSkillLearnFactor>
    <workAmount>400</workAmount>
	<anesthetize>false</anesthetize>
	<recipeUsers>

Human

	</recipeUsers>
    <surgerySuccessChanceFactor>100</surgerySuccessChanceFactor>
    <ingredients>

        <filter>
          <categories>

Medicine

          </categories>
        </filter>
        <count>1</count>

    </ingredients>
    <fixedIngredientFilter>
      <categories>

Medicine

      </categories>
    </fixedIngredientFilter>
  </RecipeDef>

  <RecipeDef ParentName="BaseBreastSurgery">
    <defName>Surgery_ExpandAreola</defName>
    expand areola
    <description>expand areola.</description>
    <workerClass>RJW_Menstruation.Recipe_ExpandAreola</workerClass>
    <jobString>expanding areola</jobString>
  </RecipeDef>

  <RecipeDef ParentName="BaseBreastSurgery">
    <defName>Surgery_ContractAreola</defName>
    contract areola
    <description>contract areola.</description>
    <workerClass>RJW_Menstruation.Recipe_ContractAreola</workerClass>
    <jobString>contracting areola</jobString>
  </RecipeDef>

  <RecipeDef ParentName="BaseBreastSurgery">
    <defName>Surgery_ExpandNipple</defName>
    expand nipple
    <description>expand nipple.</description>
    <workerClass>RJW_Menstruation.Recipe_ExpandNipple</workerClass>
    <jobString>expanding nipple</jobString>
  </RecipeDef>

  <RecipeDef ParentName="BaseBreastSurgery">
    <defName>Surgery_ContractNipple</defName>
    contract nipple
    <description>contract nipple.</description>
    <workerClass>RJW_Menstruation.Recipe_ContractNipple</workerClass>
    <jobString>contracting nipple</jobString>
  </RecipeDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<RecordDef>
		<defName>AmountofCreampied</defName>
		creampied
		<description>The amount of cums I have been creampied.</description>
		<type>Float</type>
	</RecordDef>

	<RecordDef>
		<defName>AmountofFertilizedEggs</defName>
		fertilized eggs
		<description>The amount of my eggs being raped by sperm.</description>
		<type>Int</type>
	</RecordDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>

  <StatDef>
    <defName>MaxAbsorbable</defName>
    Absorbable
    <description>Maximum fluids can be absorbed.</description>
    <category>Apparel</category>
    <minValue>0</minValue>
    <toStringStyle>FloatOne</toStringStyle>
    <formatString>{0} ml</formatString>
    <showIfUndefined>false</showIfUndefined>
    <displayPriorityInCategory>60</displayPriorityInCategory>
    <parts>

        <factorAwful>0.5</factorAwful>
        <factorPoor>0.8</factorPoor>
        <factorNormal>1</factorNormal>
        <factorGood>1.2</factorGood>
        <factorExcellent>1.4</factorExcellent>
        <factorMasterwork>2.0</factorMasterwork>
        <factorLegendary>5.0</factorLegendary>

    </parts>
  </StatDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
  <ApparelLayerDef>
    <defName>Absorber</defName>
    <label>genital</label>
    <drawOrder>500</drawOrder>
  </ApparelLayerDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>

  <ThingDef ParentName="ApparelNoQualityBase">
    <defName>Absorber_Tampon</defName>
    tampon
    <description>A tampon for absorbing fluids from vagina.
May cause infection if using too long.</description>
    <thingClass>RJW_Menstruation.Absorber_Tampon</thingClass>
    <graphicData>
      <texPath>Things/Item/Tampon</texPath>
      <graphicClass>Graphic_Single</graphicClass>
    </graphicData>
    <tickerType>Never</tickerType>
    <smeltable>false</smeltable>
	<tradeability>Sellable</tradeability>
    <statBases>
      <MaxHitPoints>20</MaxHitPoints>
      <Mass>0.01</Mass>
      <WorkToMake>1000</WorkToMake>
      <Flammability>1.0</Flammability>
      <EquipDelay>2</EquipDelay>
	  <MaxAbsorbable>10</MaxAbsorbable>
    </statBases>
    <costStuffCount>5</costStuffCount>
    <stuffCategories>

Fabric

    </stuffCategories>
    <recipeMaker>
      <unfinishedThingDef>UnfinishedApparel</unfinishedThingDef>
      <researchPrerequisite>ComplexClothing</researchPrerequisite>
      <workSpeedStat>GeneralLaborSpeed</workSpeedStat>
      <workSkill>Crafting</workSkill>
      <effectWorking>Tailor</effectWorking>
      <soundWorking>Recipe_Tailor</soundWorking>
      <recipeUsers>

ElectricTailoringBench

HandTailoringBench

      </recipeUsers>
      <useIngredientsForColor>true</useIngredientsForColor>
      <skillRequirements>
        <Crafting>4</Crafting>
      </skillRequirements>
    </recipeMaker>
    <thingCategories>

ApparelUtility

    </thingCategories>
    <apparel>
      <careIfWornByCorpse>true</careIfWornByCorpse>
      <careIfDamaged>false</careIfDamaged>
      <wearPerDay>0</wearPerDay>
	  <gender>Female</gender>
      <bodyPartGroups>

Torso

      </bodyPartGroups>
      <layers>

Absorber

      </layers>
      <tags>

Absorber

      </tags>
    </apparel>
	<modExtensions>

			<leakAfterDirty>false</leakAfterDirty>
			<effectsAfterDirty>true</effectsAfterDirty>
			<minHourstoDirtyEffect>10</minHourstoDirtyEffect>
			<dirtyDef>Absorber_Tampon_Dirty</dirtyDef>

	</modExtensions>
  </ThingDef>

  <ThingDef ParentName="ApparelNoQualityBase">
	<defName>Absorber_Tampon_Dirty</defName>
    dirty tampon
    <description>An wet used tampon.
May cause infection.</description>
    <thingClass>RJW_Menstruation.Absorber_Tampon</thingClass>
    <graphicData>
      <texPath>Things/Item/Tampon</texPath>
      <graphicClass>Graphic_Single</graphicClass>
    </graphicData>
    <tickerType>Never</tickerType>
    <smeltable>false</smeltable>
	<tradeability>None</tradeability>
    <statBases>
      <MaxHitPoints>20</MaxHitPoints>
      <Mass>0.05</Mass>
	  <MarketValue>0</MarketValue>
      <WorkToMake>1000</WorkToMake>
      <Flammability>0.2</Flammability>
      <EquipDelay>2</EquipDelay>
	  <MaxAbsorbable>10</MaxAbsorbable>
	  <Cleanliness>-5</Cleanliness>
    </statBases>
    <stuffCategories>

Fabric

    </stuffCategories>
    <thingCategories>

ApparelUtility

    </thingCategories>
    <apparel>
      <careIfWornByCorpse>true</careIfWornByCorpse>
      <careIfDamaged>false</careIfDamaged>
      <wearPerDay>0</wearPerDay>
	  <gender>Female</gender>
      <bodyPartGroups>

Torso

      </bodyPartGroups>
      <layers>

Absorber

      </layers>
      <tags>

Absorber

      </tags>
    </apparel>
	<modExtensions>

			<leakAfterDirty>false</leakAfterDirty>
			<effectsAfterDirty>true</effectsAfterDirty>
			<minHourstoDirtyEffect>8</minHourstoDirtyEffect>
			<dirtyDef>Absorber_Tampon_Dirty</dirtyDef>

	</modExtensions>
  </ThingDef>

  <ThingDef ParentName="ApparelNoQualityBase">
    <defName>Absorber_Pad</defName>
    sanitary pad
    <description>A pad for absorbing fluids from vagina.</description>
    <thingClass>RJW_Menstruation.Absorber</thingClass>
    <graphicData>
      <texPath>Things/Item/Pad</texPath>
      <graphicClass>Graphic_Single</graphicClass>
    </graphicData>
    <tickerType>Never</tickerType>
    <smeltable>false</smeltable>
	<tradeability>Sellable</tradeability>
    <statBases>
      <MaxHitPoints>40</MaxHitPoints>
      <Mass>0.02</Mass>
      <WorkToMake>1000</WorkToMake>
      <Flammability>1.0</Flammability>
      <EquipDelay>4</EquipDelay>
	  <MaxAbsorbable>25</MaxAbsorbable>
    </statBases>
    <costStuffCount>10</costStuffCount>
    <stuffCategories>

Fabric

    </stuffCategories>
    <recipeMaker>
      <unfinishedThingDef>UnfinishedApparel</unfinishedThingDef>
      <workSpeedStat>GeneralLaborSpeed</workSpeedStat>
      <workSkill>Crafting</workSkill>
      <effectWorking>Tailor</effectWorking>
      <soundWorking>Recipe_Tailor</soundWorking>
      <recipeUsers>

ElectricTailoringBench

HandTailoringBench

      </recipeUsers>
      <useIngredientsForColor>true</useIngredientsForColor>
      <skillRequirements>
        <Crafting>4</Crafting>
      </skillRequirements>
    </recipeMaker>
    <thingCategories>

ApparelUtility

    </thingCategories>
    <apparel>
      <careIfWornByCorpse>true</careIfWornByCorpse>
      <careIfDamaged>false</careIfDamaged>
      <wearPerDay>0</wearPerDay>
	  <gender>Female</gender>
      <bodyPartGroups>

Torso

      </bodyPartGroups>
      <layers>

Absorber

      </layers>
      <tags>

Absorber

      </tags>
    </apparel>
	<modExtensions>

			<leakAfterDirty>true</leakAfterDirty>
			<effectsAfterDirty>false</effectsAfterDirty>
			<dirtyDef>Absorber_Pad_Dirty</dirtyDef>

	</modExtensions>
  </ThingDef>

  <ThingDef ParentName="ApparelNoQualityBase">
	<defName>Absorber_Pad_Dirty</defName>
    wet sanitary pad
    <description>An wet used pad.</description>
    <thingClass>RJW_Menstruation.Absorber</thingClass>
    <graphicData>
      <texPath>Things/Item/Pad</texPath>
      <graphicClass>Graphic_Single</graphicClass>
    </graphicData>
    <tickerType>Never</tickerType>
    <smeltable>false</smeltable>
	<tradeability>None</tradeability>
    <statBases>
      <MaxHitPoints>40</MaxHitPoints>
      <Mass>0.10</Mass>
	  <MarketValue>0</MarketValue>
      <WorkToMake>1000</WorkToMake>
      <Flammability>0.2</Flammability>
      <EquipDelay>4</EquipDelay>
	  <MaxAbsorbable>25</MaxAbsorbable>
	  <Cleanliness>-5</Cleanliness>
    </statBases>
    <stuffCategories>

Fabric

    </stuffCategories>
    <thingCategories>

ApparelUtility

    </thingCategories>
    <apparel>
      <careIfWornByCorpse>true</careIfWornByCorpse>
      <careIfDamaged>false</careIfDamaged>
      <wearPerDay>0</wearPerDay>
	  <gender>Female</gender>
      <bodyPartGroups>

Torso

      </bodyPartGroups>
      <layers>

Absorber

      </layers>
      <tags>

Absorber

      </tags>
    </apparel>
	<modExtensions>

			<leakAfterDirty>true</leakAfterDirty>
			<effectsAfterDirty>false</effectsAfterDirty>
			<dirtyDef>Absorber_Pad_Dirty</dirtyDef>

	</modExtensions>
  </ThingDef>
</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<ThingDef ParentName="BaseFilth">
		<defName>FilthMixture</defName>
		<label>mixture</label>
		<thingClass>RJW_Menstruation.Filth_Colored</thingClass>
		<statBases>
			<Beauty>-30</Beauty>
			<Cleanliness>-10</Cleanliness>
		</statBases>
		<graphicData>
			<graphicClass>Graphic_Random</graphicClass>
			<texPath>Things/Filth/PoolSoft</texPath>
			<color>(255, 255, 255, 180)</color>
		</graphicData>
		<filth>
			<rainWashes>true</rainWashes>
			<cleaningWorkToReduceThickness>40</cleaningWorkToReduceThickness>
			<canFilthAttach>true</canFilthAttach>
		</filth>
	</ThingDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8" ?>

<Defs>
	<ThoughtDef>
		<defName>LeakingFluids</defName>
		<thoughtClass>Thought_Memory</thoughtClass>
		<durationDays>0.05</durationDays>
		<stackLimit>1</stackLimit>
		<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
		<stages>

				dripping fluids
				<description>It bothers me.</description>
				<baseMoodEffect>-2</baseMoodEffect>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>CameInsideF</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>7.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stages>

				{0} came inside
				<description>I'm worried i might get pregnant.</description>
				<baseMoodEffect>-3</baseMoodEffect>
				<baseOpinionOffset>-2</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>CameInsideFLowFert</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>3.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stages>

				{0} came inside
				<description>I'm worried i might get pregnant.
The chance is low, but...</description>
				<baseMoodEffect>-1</baseMoodEffect>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>CameInsideFFetish</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>3.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stages>

				{0} came inside
				<description>I might get pregnant.</description>
				<baseMoodEffect>10</baseMoodEffect>
				<baseOpinionOffset>5</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>CameInsideFFetishSafe</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>3.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stages>

				{0} came inside
				<description>I loved it.</description>
				<baseMoodEffect>3</baseMoodEffect>
				<baseOpinionOffset>1</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>CameInsideM</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>1.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
		<stages>

				came inside of {0}
				<description>Feel so good.</description>
				<baseMoodEffect>2</baseMoodEffect>
				<baseOpinionOffset>1</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>HaterCameInsideFSafe</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>3.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stages>

				{0} came inside
				<description>The chance is low. But i don't like it.</description>
				<baseMoodEffect>-2</baseMoodEffect>
				<baseOpinionOffset>-5</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>HaterCameInsideF</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>7.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
		<stages>

				{0} came inside
				<description>I don't want to be pregnant with his baby</description>
				<baseMoodEffect>-5</baseMoodEffect>
				<baseOpinionOffset>-10</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>HaterCameInsideM</defName>
		<thoughtClass>Thought_MemorySocial</thoughtClass>
		<durationDays>1.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
		<stages>

				came inside of {0}
				<description>i came inside of that bitch</description>
				<baseMoodEffect>5</baseMoodEffect>
				<baseOpinionOffset>1</baseOpinionOffset>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>UnwantedPregnancy</defName>
		<thoughtClass>Thought_Memory</thoughtClass>
		<durationDays>14.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stages>

				unwanted pregnancy
				<description>How do i...</description>
				<baseMoodEffect>-10</baseMoodEffect>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>UnwantedPregnancyMild</defName>
		<thoughtClass>Thought_Memory</thoughtClass>
		<durationDays>14.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stages>

				unwanted pregnancy
				<description>How do i...</description>
				<baseMoodEffect>-3</baseMoodEffect>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>TookContraptivePill</defName>
		<thoughtClass>Thought_Memory</thoughtClass>
		<durationDays>7.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stages>

				took contraptive pill
				<description>It will be okay.</description>
				<baseMoodEffect>1</baseMoodEffect>

		</stages>
	</ThoughtDef>

	<ThoughtDef>
		<defName>HateTookContraptivePill</defName>
		<thoughtClass>Thought_Memory</thoughtClass>
		<durationDays>7.0</durationDays>
		<stackLimit>5</stackLimit>
		<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
		<stages>

				took contraptive pill
				<description>I want to get pregnant.</description>
				<baseMoodEffect>-3</baseMoodEffect>

		</stages>
	</ThoughtDef>

</Defs>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <Absorber.label>生殖器</Absorber.label>
</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>

<LanguageData>
  <Hediff_MenstrualCramp.label>中枢性疼痛</Hediff_MenstrualCramp.label>
  <Hediff_MenstrualCramp.description>经期中</Hediff_MenstrualCramp.description>
  <Hediff_MenstrualCramp.stages.0.label>不快</Hediff_MenstrualCramp.stages.0.label>
  <Hediff_MenstrualCramp.stages.1.label>恼人</Hediff_MenstrualCramp.stages.1.label>
  <Hediff_MenstrualCramp.stages.2.label>疼痛</Hediff_MenstrualCramp.stages.2.label>
  <Hediff_MenstrualCramp.stages.3.label>痛苦</Hediff_MenstrualCramp.stages.3.label>
  <Hediff_Climacteric.label>更年期</Hediff_Climacteric.label>
  <Hediff_Climacteric.description>到了更年期</Hediff_Climacteric.description>
  <Hediff_Climacteric.stages.0.label>初期</Hediff_Climacteric.stages.0.label>
  <Hediff_Climacteric.stages.1.label>中期</Hediff_Climacteric.stages.1.label>
  <Hediff_Climacteric.stages.2.label>后期</Hediff_Climacteric.stages.2.label>
  <Hediff_Climacteric.stages.3.label>更年期</Hediff_Climacteric.stages.3.label>
  <Hediff_Menopause.label>更年期</Hediff_Menopause.label>
  <Hediff_Menopause.description>不孕</Hediff_Menopause.description>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <VaginaWashing.reportString>清洗阴道</VaginaWashing.reportString>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <MaxAbsorbable.label>可吸收量</MaxAbsorbable.label>
  <MaxAbsorbable.description>最大可吸收的液体量</MaxAbsorbable.description>

</LanguageData>


code:
<?xml version="1.0" encoding="UTF-8"?>

<LanguageData>

<Absorber_Tampon.label>卫生棉条</Absorber_Tampon.label>

<Absorber_Tampon.description>从阴道吸收液体的卫生棉条</Absorber_Tampon.description>

<Absorber_Tampon_Dirty.label>湿的卫生棉条</Absorber_Tampon_Dirty.label>

<Absorber_Tampon_Dirty.description>使用过的湿卫生棉条</Absorber_Tampon_Dirty.description>

<Absorber_Pad.label>卫生棉</Absorber_Pad.label>

<Absorber_Pad.description>从阴道吸收液体的卫生棉</Absorber_Pad.description>

<Absorber_Pad_Dirty.label>湿的卫生棉</Absorber_Pad_Dirty.label>

<Absorber_Pad_Dirty.description>使用过的湿卫生棉</Absorber_Pad_Dirty.description>

<OvaryRegenerationPill.label>卵巢再生药物</OvaryRegenerationPill.label>

<OvaryRegenerationPill.description>使卵巢再生以增加可排卵的卵子
卵子消耗量越大，效果越差
不能缓解更年期症状</OvaryRegenerationPill.description>

<SuperovulationInducingAgent.label>排卵药</SuperovulationInducingAgent.label>

<SuperovulationInducingAgent.description>诱导排卵的药物
可导致更年期提前</SuperovulationInducingAgent.description>

<FilthMixture.label>混合物</FilthMixture.label>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <LeakingFluids.stages.0.label>裤湿啦</LeakingFluids.stages.0.label>
  <LeakingFluids.stages.0.description>真让人困恼... </LeakingFluids.stages.0.description>
  <CameInsideF.stages.0.label>被{0}中出了</CameInsideF.stages.0.label>
  <CameInsideF.stages.0.description>我担心我可能会怀孕... </CameInsideF.stages.0.description>
  <CameInsideFLowFert.stages.0.label>被{0}中出了</CameInsideFLowFert.stages.0.label>
  <CameInsideFLowFert.stages.0.description>虽然几率很低，但我还是担心怀孕... </CameInsideFLowFert.stages.0.description>
  <CameInsideFFetish.stages.0.label>被{0}中出了</CameInsideFFetish.stages.0.label>
  <CameInsideFFetish.stages.0.description>我想我怀孕了</CameInsideFFetish.stages.0.description>
  <CameInsideFFetishSafe.stages.0.label>被{0}中出了</CameInsideFFetishSafe.stages.0.label>
  <CameInsideFFetishSafe.stages.0.description>我爱做爱</CameInsideFFetishSafe.stages.0.description>
  <CameInsideM.stages.0.label>中出了{0}</CameInsideM.stages.0.label>
  <CameInsideM.stages.0.description>超爽的</CameInsideM.stages.0.description>
  <HaterCameInsideF.stages.0.label>被{0}中出了</HaterCameInsideF.stages.0.label>
  <HaterCameInsideF.stages.0.description>那龟孙子上了我，我不想怀上他的孩子...</HaterCameInsideF.stages.0.description>
  <HaterCameInsideFSafe.stages.0.label>被{0}中出了</HaterCameInsideFSafe.stages.0.label>
  <HaterCameInsideFSafe.stages.0.description>那龟孙子上了我....</HaterCameInsideFSafe.stages.0.description>
  <HaterCameInsideM.stages.0.label>中出了{0}</HaterCameInsideM.stages.0.label>
  <HaterCameInsideM.stages.0.description>我上了一个婊子</HaterCameInsideM.stages.0.description>
  <UnwantedPregnancy.stages.0.label>不想要的怀孕</UnwantedPregnancy.stages.0.label>
  <UnwantedPregnancy.stages.0.description>我该怎麽办？... </UnwantedPregnancy.stages.0.description>
</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <Mod_Title>RJW Menstruation Cycle</Mod_Title>

  <Menstrual_Blood>月经血</Menstrual_Blood>
  <Info_noCum>清空</Info_noCum>
  <Stage_Follicular>卵泡期</Stage_Follicular>
  <Stage_Ovulatory>排卵</Stage_Ovulatory>
  <Stage_Luteal>黄体期</Stage_Luteal>
  <Stage_Bleeding>月经来潮</Stage_Bleeding>
  <Stage_Fertilized>已受精</Stage_Fertilized>
  <Stage_Pregnant>怀孕</Stage_Pregnant>
  <Stage_Recover>从出生中恢复</Stage_Recover>
  <Stage_None>无</Stage_None>
  <Stage_Climacteric>更年期</Stage_Climacteric>
  <Dialog_WombInfo01>状态</Dialog_WombInfo01>
  <Dialog_WombInfo02>胎儿</Dialog_WombInfo02>
  <Dialog_WombInfo03>父亲</Dialog_WombInfo03>
  <Dialog_WombInfo04>阴道精液列表</Dialog_WombInfo04>
  <Dialog_WombInfo05>已受精</Dialog_WombInfo05>
  <Dialog_WombInfo06>受精中</Dialog_WombInfo06>
  <Dialog_WombInfo07>排卵</Dialog_WombInfo07>
  <Dialog_WombInfo08></Dialog_WombInfo08>
  <Dialog_WombInfo09></Dialog_WombInfo09>

  <Option1_Label>激活子宫图标</Option1_Label>
  <Option1_Desc>激活子宫图标框</Option1_Desc>
  <Option2_Label>激活动物经期</Option2_Label>
  <Option2_Desc>仿真动物的经期.
此选项将在保存读取后生效
不推荐开启此选项</Option2_Desc>
  <Option3_Label>植入机会</Option3_Label>
  <Option3_Desc>设置受精卵的植入机会</Option3_Desc>
  <Option4_Label>受精的机会</Option4_Label>
  <Option4_Desc>设置每小时受精的机会</Option4_Desc>
  <Option5_Label>每小时阴道中的精液量衰减率</Option5_Label>
  <Option5_Desc>阴道中的精液量将以这个比率减少</Option5_Desc>
  <Option6_Label>每小时生育率衰减率</Option6_Label>
  <Option6_Desc>精液列表的生育率将以这个比率减少</Option6_Desc>
  <Option7_Label>循环加速</Option7_Label>
  <Option7_Desc>加快月经周期</Option7_Desc>
  <Option8_Label>调试</Option8_Label>
  <Option8_Desc>显示调试信息</Option8_Desc>
  <Option9_Label>子宫状态</Option9_Label>
  <Option9_Desc>在状态窗口中绘制子宫图标</Option9_Desc>
  <Option10_Label>阴道状态</Option10_Label>
  <Option10_Desc>在状态窗口中绘制阴道和肛门图标</Option10_Desc>
  <Option11_Label>胎儿信息级别</Option11_Label>
  <Option11_Desc_1>显示有关胎儿的所有信息</Option11_Desc_1>
  <Option11_Desc_2>显示妊娠後胎儿的所有信息</Option11_Desc_2>
  <Option11_Desc_3>不显示有关胎儿的信息，但显示怀孕後胎儿的图象</Option11_Desc_3>
  <Option11_Desc_4>不显示胎儿图象和信息</Option11_Desc_4>
  <Option12_Label>激活更年期</Option12_Label>
  <Option12_Desc>激活更年期效果，使小人随着时间的推移而变得不育
如果您较长寿的外星人种族有碰到任何问题，请关闭此选项.
此选项将在保存读取后生效</Option12_Desc>
  <Option13_Label>多重怀孕</Option13_Label>
  <Option13_Desc>使用多重怀孕代替RJW的默认怀孕</Option13_Desc>
  <Option14_Label>激活异卵双胞胎</Option14_Label>
  <Option14_Desc>激活复数个卵子可以个别受精</Option14_Desc>
  <Option15_Label>激活双胞胎</Option15_Label>
  <Option15_Desc>允许单个卵子生成多个后代</Option15_Desc>
  <Option16_Label>双胞胎出现率</Option16_Label>
  <Option16_Desc>设置双胞胎的出现率</Option16_Desc>
  <Option17_Label>最大双胞胎数量</Option17_Label>
  <Option17_Desc>设置最大双胞胎数量</Option17_Desc>

  <FloatMenu_CleanSelf>清洗阴道</FloatMenu_CleanSelf>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>

<LanguageData>
  <Hediff_MenstrualCramp.label>中樞性疼痛</Hediff_MenstrualCramp.label>
  <Hediff_MenstrualCramp.description>經期中</Hediff_MenstrualCramp.description>
  <Hediff_MenstrualCramp.stages.0.label>不快</Hediff_MenstrualCramp.stages.0.label>
  <Hediff_MenstrualCramp.stages.1.label>惱人</Hediff_MenstrualCramp.stages.1.label>
  <Hediff_MenstrualCramp.stages.2.label>疼痛</Hediff_MenstrualCramp.stages.2.label>
  <Hediff_MenstrualCramp.stages.3.label>痛苦</Hediff_MenstrualCramp.stages.3.label>
  <Hediff_Climacteric.label>更年期</Hediff_Climacteric.label>
  <Hediff_Climacteric.description>到了更年期</Hediff_Climacteric.description>
  <Hediff_Climacteric.stages.0.label>初期</Hediff_Climacteric.stages.0.label>
  <Hediff_Climacteric.stages.1.label>中期</Hediff_Climacteric.stages.1.label>
  <Hediff_Climacteric.stages.2.label>後期</Hediff_Climacteric.stages.2.label>
  <Hediff_Climacteric.stages.3.label>更年期</Hediff_Climacteric.stages.3.label>
  <Hediff_Menopause.label>更年期</Hediff_Menopause.label>
  <Hediff_Menopause.description>不孕</Hediff_Menopause.description>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <VaginaWashing.reportString>清洗陰道</VaginaWashing.reportString>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <MaxAbsorbable.label>可吸收量</MaxAbsorbable.label>
  <MaxAbsorbable.description>最大可吸收的液體量</MaxAbsorbable.description>

</LanguageData>


code:
<?xml version="1.0" encoding="UTF-8"?>

<LanguageData>

<Absorber_Tampon.label>衛生棉條</Absorber_Tampon.label>

<Absorber_Tampon.description>從陰道吸收液體的衛生棉條</Absorber_Tampon.description>

<Absorber_Tampon_Dirty.label>濕的衛生棉條</Absorber_Tampon_Dirty.label>

<Absorber_Tampon_Dirty.description>使用過的濕衛生棉條</Absorber_Tampon_Dirty.description>

<Absorber_Pad.label>衛生棉</Absorber_Pad.label>

<Absorber_Pad.description>從陰道吸收液體的衛生棉</Absorber_Pad.description>

<Absorber_Pad_Dirty.label>濕的衛生棉</Absorber_Pad_Dirty.label>

<Absorber_Pad_Dirty.description>使用過的濕衛生棉</Absorber_Pad_Dirty.description>

<OvaryRegenerationPill.label>卵巢再生藥物</OvaryRegenerationPill.label>

<OvaryRegenerationPill.description>使卵巢再生以增加可排卵的卵子
卵子消耗量越大，效果越差
不能緩解更年期症狀</OvaryRegenerationPill.description>

<SuperovulationInducingAgent.label>排卵藥</SuperovulationInducingAgent.label>

<SuperovulationInducingAgent.description>誘導排卵的藥物
可導致更年期提前</SuperovulationInducingAgent.description>

<FilthMixture.label>混合物</FilthMixture.label>

</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <LeakingFluids.stages.0.label>褲濕啦</LeakingFluids.stages.0.label>
  <LeakingFluids.stages.0.description>真讓人困惱... </LeakingFluids.stages.0.description>
  <CameInsideF.stages.0.label>被{0}中出了</CameInsideF.stages.0.label>
  <CameInsideF.stages.0.description>我擔心我可能會懷孕... </CameInsideF.stages.0.description>
  <CameInsideFLowFert.stages.0.label>被{0}中出了</CameInsideFLowFert.stages.0.label>
  <CameInsideFLowFert.stages.0.description>雖然機率很低，但我還是擔心懷孕... </CameInsideFLowFert.stages.0.description>
  <CameInsideFFetish.stages.0.label>被{0}中出了</CameInsideFFetish.stages.0.label>
  <CameInsideFFetish.stages.0.description>我想我懷孕了</CameInsideFFetish.stages.0.description>
  <CameInsideFFetishSafe.stages.0.label>被{0}中出了</CameInsideFFetishSafe.stages.0.label>
  <CameInsideFFetishSafe.stages.0.description>我愛做愛</CameInsideFFetishSafe.stages.0.description>
  <CameInsideM.stages.0.label>中出了{0}</CameInsideM.stages.0.label>
  <CameInsideM.stages.0.description>超爽的</CameInsideM.stages.0.description>
  <HaterCameInsideF.stages.0.label>被{0}中出了</HaterCameInsideF.stages.0.label>
  <HaterCameInsideF.stages.0.description>那龜孫子上了我，我不想懷上他的孩子...</HaterCameInsideF.stages.0.description>
  <HaterCameInsideFSafe.stages.0.label>被{0}中出了</HaterCameInsideFSafe.stages.0.label>
  <HaterCameInsideFSafe.stages.0.description>那龜孫子上了我....</HaterCameInsideFSafe.stages.0.description>
  <HaterCameInsideM.stages.0.label>中出了{0}</HaterCameInsideM.stages.0.label>
  <HaterCameInsideM.stages.0.description>我上了一個婊子</HaterCameInsideM.stages.0.description>
  <UnwantedPregnancy.stages.0.label>不想要的懷孕</UnwantedPregnancy.stages.0.label>
  <UnwantedPregnancy.stages.0.description>我該怎麼辦？... </UnwantedPregnancy.stages.0.description>
</LanguageData>


code:
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
  <Mod_Title>RJW Menstruation Cycle</Mod_Title>

  <Menstrual_Blood>月經血</Menstrual_Blood>
  <Info_noCum>清空</Info_noCum>
  <Stage_Follicular>卵泡期</Stage_Follicular>
  <Stage_Ovulatory>排卵</Stage_Ovulatory>
  <Stage_Luteal>黃體期</Stage_Luteal>
  <Stage_Bleeding>月經來潮</Stage_Bleeding>
  <Stage_Fertilized>已受精</Stage_Fertilized>
  <Stage_Pregnant>懷孕</Stage_Pregnant>
  <Stage_Recover>從出生中恢復</Stage_Recover>
  <Stage_None>無</Stage_None>
  <Stage_Climacteric>更年期</Stage_Climacteric>
  <Dialog_WombInfo01>狀態</Dialog_WombInfo01>
  <Dialog_WombInfo02>胎兒</Dialog_WombInfo02>
  <Dialog_WombInfo03>父親</Dialog_WombInfo03>
  <Dialog_WombInfo04>陰道精液列表</Dialog_WombInfo04>
  <Dialog_WombInfo05>已受精</Dialog_WombInfo05>
  <Dialog_WombInfo06>受精中</Dialog_WombInfo06>
  <Dialog_WombInfo07>排卵</Dialog_WombInfo07>
  <Dialog_WombInfo08></Dialog_WombInfo08>
  <Dialog_WombInfo09></Dialog_WombInfo09>

  <Option1_Label>啟用子宮圖標</Option1_Label>
  <Option1_Desc>啟用子宮圖標框</Option1_Desc>
  <Option2_Label>啟用動物經期</Option2_Label>
  <Option2_Desc>模擬動物的經期.
此選項將在保存讀取後生效
不推薦開啟此選項</Option2_Desc>
  <Option3_Label>植入機會</Option3_Label>
  <Option3_Desc>設置受精卵的植入機會</Option3_Desc>
  <Option4_Label>受精的機會</Option4_Label>
  <Option4_Desc>設置每小時受精的機會</Option4_Desc>
  <Option5_Label>每小時陰道中的精液量衰減率</Option5_Label>
  <Option5_Desc>陰道中的精液量將以這個比率減少</Option5_Desc>
  <Option6_Label>每小時生育率衰減率</Option6_Label>
  <Option6_Desc>精液列表的生育率將以這個比率減少</Option6_Desc>
  <Option7_Label>循環加速</Option7_Label>
  <Option7_Desc>加快月經週期</Option7_Desc>
  <Option8_Label>除錯</Option8_Label>
  <Option8_Desc>顯示除錯資訊</Option8_Desc>
  <Option9_Label>子宮狀態</Option9_Label>
  <Option9_Desc>在狀態窗口中繪製子宮圖標</Option9_Desc>
  <Option10_Label>陰道狀態</Option10_Label>
  <Option10_Desc>在狀態窗口中繪製陰道和肛門圖標</Option10_Desc>
  <Option11_Label>胎兒信息級別</Option11_Label>
  <Option11_Desc_1>顯示有關胎兒的所有信息</Option11_Desc_1>
  <Option11_Desc_2>顯示妊娠後胎兒的所有信息</Option11_Desc_2>
  <Option11_Desc_3>不顯示有關胎兒的信息，但顯示懷孕後胎兒的圖像</Option11_Desc_3>
  <Option11_Desc_4>不顯示胎兒圖像和信息</Option11_Desc_4>
  <Option12_Label>啟用更年期</Option12_Label>
  <Option12_Desc>啟用更年期效果，使小人隨著時間的推移而變得不育
如果您較長壽的外星人種族有碰到任何問題，請關閉此選項.
此選項將在保存讀取後生效</Option12_Desc>
  <Option13_Label>多重懷孕</Option13_Label>
  <Option13_Desc>使用多重懷孕代替RJW的默認懷孕</Option13_Desc>
  <Option14_Label>啟用異卵雙胞胎</Option14_Label>
  <Option14_Desc>啟用複數個卵子可以個別受精</Option14_Desc>
  <Option15_Label>啟用雙胞胎</Option15_Label>
  <Option15_Desc>允許單個卵子產生多個後代</Option15_Desc>
  <Option16_Label>雙胞胎出現率</Option16_Label>
  <Option16_Desc>設置雙胞胎的出現率</Option16_Desc>
  <Option17_Label>最大雙胞胎數量</Option17_Label>
  <Option17_Desc>設置最大雙胞胎數量</Option17_Desc>

  <FloatMenu_CleanSelf>清洗陰道</FloatMenu_CleanSelf>

</LanguageData>